Tehnični članak

Varno ponavljanje nezaupanih EMF in WMF v HotXLS

Delovni zvezek Excel lahko nosi slike EMF in WMF in konvencionalni način risanja ene je izročiti tok bajtov predvajalniku metafila operacijskega sistema. To je odločitev, vredna neposrednega ogleda: metafile je serializiran tok ukazov za grafični API in predvajanje enega nazaj pomeni pustiti datoteki, ki je prispla po e-pošti, gnati grafični gonilnik. HotXLS vzame drugo pot. XLSDecodeVectorScene razčleni metafile sam, validira glavo, vsako velikost zapisa, deklarirano skupno število zapisov in natanko umestitev zapisa konca datoteke, odkloni zapise escape naravnost in vrne TXLSVectorScene primitivnih ukazov risanja, ki jih zaledji Canvas in SVG ponovita skozi svojo lastno kodo. Nobeno predvajanje gonilnika ni vpleteno na nobeni točki

HotXLS razčleni bajte nezaupanega delovnega lista EMF in WMF z XLSDecodeVectorScene v seznam ukazov TXLSVectorScene namesto predvajanja metafila GDI
HotXLS razčleni metafile sam in vrne primitivne ukaze za ponovitev Canvas in SVG; konvencionalna pot izvede tok bajtov na grafičnem skladu

Kupčija je pokritost za omejitev. Beli seznam ukazov, usmerjen na pravokotnike, ne bo reprodukal vsakega metafila, ki ga lahko ustvari oblikovalec, zato scena poroča, koliko zapisov risanja ni mogla predstavljati, klicatelj pa se odloči, kaj o tem. Za strežniški proces, ki upodablja dokumente, ki jih ni ustvaril, je ta kupčija prava smer

Zakaj je predvajanje metafila slab primer za nezaupan vhod?

Ker oblika ni slika, je program. Tok zapisov EMF upravlja sklad stanj konteksta naprave, dodeljuje in izbira objekte iz tabele ročajev in lahko nosi zapise escape, katerih tovor je posredovan grafičnemu gonilniku. Ponavljanje njega vadi poti v grafičnem skladu platforme, ki so bile napisane na predpostavki, da je metafile prišel s sodelujoče aplikacije na istem stroju. Ko je vhod priloga preglednice, ta predpostavka je odšla in nobena količina skrbnosti znotraj knjižnice preglednic ne pomaga, ker knjižnica ni komponenta, ki dela razčlenjevanje

To je isto utemeljevanje, ki upravlja plast vsebnika. Delovni zvezek je arhiv ZIP in HotXLS validira njegov osrednji imenik namesto zaupanja deklariranim odmikom, kot je opisano v članku o validaciji ZIP end-of-central-directory. Tovori metafila so naslednja plast istega problema

Kaj dekodirnik preveri, preden kaj nariše

Validacija je strukturna in zgodi se na začetku, ker je razčlenjevalnik, ki začne risati in validira, ko gre, že ukrepal na podatkih, ki jih ni preveril. Glava se mora ujemati strogo in ne verjetno. Vsak zapis mora deklarirati velikost, ki se prilega znotraj preostalega predpomnilnika in je dovolj velika za svoja fiksna polja. Število zapisov, ki ga glava deklarira, se mora ujemati z zapisi, dejansko prisotnimi. Zapis konca datoteke mora sedeti natanko tam, kjer se tok konča, in ne le nekje blizu njega, kar zapre trik končnih smeti, ki skriva drugi tovor za veljavno sliko

Onkraj strukture je dekodirnik odpoved-zaprto na semantiki. Zapisi escape so odklonjeni, ne preskočeni. Zapis, ki spreminja stanje, ki ga dekodirnik ne modelira, povzroči odpoved dekodiranja namesto ignoriranja, ker ignoriranje spremembe stanja pomeni, da je vsak naknadni ukaz risanja izveden v stanju, ki ga datoteka ni zahtevala, in rezultat je slika, ki je napačna na način, ki ga nihče ne more predvideti. Zapisi risanja zunaj podprtega nabora ukazov so druga zadeva: ti so šteti in preskočeni, ker je manjkajoča oblika vidna, poročljiva vrzel in ne tiho pokvarjenost

XLSDecodeVectorScene preveri glavo, velikosti zapisov, skupne seštevke in umestitev EOF na začetku, nato odkloni zapise escape in šteje nepodprte zapise risanja
Strukturni pregledi tečejo na začetku in semantika odpoved-zaprto odkloni zapise escape, medtem ko so nepodprti zapisi risanja samo šteti in preskočeni

Proračuni so del pogodbe oblike

Vektorske oblike imajo svojo različico bombe razširjanja. Nekaj kilobajtov zapisov lahko deklarira polilinije s stotinami milijonov točk ali sliko, katere deklarirane mere se pomnožijo v terabajte. Meje so zato morajo biti izrecne konstante in ne karkoli, kar se stroju slučajno preživi

// Iz lxVectorScene: proračun dekodiranja, izjavljen in ne impliciran
XL_VECTOR_MAX_RECORDS           = 1000000;
XL_VECTOR_MAX_HANDLES           = 4096;
XL_VECTOR_MAX_DC_DEPTH          = 32;
XL_VECTOR_MAX_COMMANDS          = 100000;
XL_VECTOR_MAX_POINTS_PER_RECORD = 100000;
XL_VECTOR_MAX_TOTAL_POINTS      = 2000000;
XL_VECTOR_MAX_TEXT_CHARS        = 4096;
XL_VECTOR_MAX_TOTAL_TEXT_CHARS  = 1000000;
XL_VECTOR_MAX_IMAGE_SIDE        = 8192;
XL_VECTOR_MAX_IMAGE_PIXELS      = 32 * 1024 * 1024;
XL_VECTOR_MAX_IMAGE_BYTES       = 64 * 1024 * 1024;
XL_VECTOR_MAX_COORD             = 1000000000;

Dve od teh si zaslužita opombo. Omejitev globine konteksta naprave 32 obstaja, ker so zapisi SaveDC in RestoreDC ugnezdeni in neuravnotežen tok lahko potiska za vedno; 32 je radodarno za prave metafile in poceni za uveljavljanje. Omejitev koordinat obstaja, ker se koordinate hranijo v transformacijo in vrednost blizu mej razpona celih števil proizvede preoblikovan rezultat, ki je ali neskončen ali se zvije, po čemer je vsak izračun omejevalnega okvira nizvodno nesmisel. Pripenjanje koordinat ob času razčlenjevanja je veliko lažje za razumevanje kot branjenje vsakega potrošnika geometrije

Konstante proračuna dekodiranja v HotXLS lxVectorScene za zapise, ročaje, globino DC, ukaze, točke, besedilo, velikost slike in pripenjanje koordinat
Vsaka meja je poimenovana konstanta, uveljavljena med razčlenjevanjem; omejitev globine DC in pripenjanje koordinat si zaslužita največ pozornosti

Uporaba scene

Dekodirnik izroči nazaj objekt, ki ga lastite, število ukazov, nominalno velikost in število zapisov risanja, ki se je odločil ne predstavljati

uses
  lxVectorScene;

var
  Scene: TXLSVectorScene;
  Error: WideString;
  I: Integer;
begin
  // Data drži surovi tovor slike, vzet iz delovnega zvezka
  if not XLSDecodeVectorScene(Data, xlsvfEmf, Scene, Error) then
  begin
    // Odklonjeno: glava, meje, skupne seštevke, umestitev EOF ali proračun
    LogReject('metafile rejected: ' + Error);
    Exit;
  end;
  try
    if Scene.SkippedDrawRecords > 0 then
      LogWarning(Format('%d drawing records outside the safe subset',
        [Scene.SkippedDrawRecords]));
    for I := 0 to Scene.Count - 1 do
      case Scene.Commands[I].Kind of
        xlsvcRectangle: DrawRect(Scene.Commands[I]);
        xlsvcEllipse:   DrawEllipse(Scene.Commands[I]);
        xlsvcPolyline,
        xlsvcPolygon,
        xlsvcBezier:    DrawPath(Scene.Commands[I]);
        xlsvcText:      DrawText(Scene.Commands[I]);
        xlsvcImage:     DrawImage(Scene.Commands[I]);
      end;
  finally
    Scene.Free;
  end;
end;

Zapis ukaza nosi vse, kar potrebuje zaledje, in ničesar, kar zahteva napravo: prisotnost peresa, barvo, širino in slog; prisotnost čopiča in barvo; geometrijo; in za besedilo niz, ime pisave, velikost, sloge in poravnavo. To je tisto, kar naredi isto sceno uporabno tako s strani upodobitelja platna na zaslonu kot zapisovalnika SVG in je razlog, zakaj vektorska pot ne divergira med predogledom in izvozom. Upodabljanje na zaslonu vsebine delovnega lista na splošno je pokrito v članku o upodabljanju lastne mreže VCL

Odklon slike ne poškoduje delovnega zvezka

Pomembna lastnost te zasnove je, da odklonjeno dekodiranje vpliva samo na upodabljanje. Izvirni tovor ostane v modelu, zato delovni zvezek, ki je odprt in znova shranjen, iznese svoje slike metafila bajt za bajtom, ne glede na to, ali jih je varni dekodirnik znal narisati. Obstoječa omejena rastrska pot prav tako ostane razpoložljiva kot zasilna rešitev. Z drugimi besedami, strog razčlenjevalnik ogradi tisto, kar se izvede, in ne tistega, kar se ohrani, kar je razlikovanje, ki pusti varnostno motivirano spremembo odpluti brez spreminjanja v spremembo izgube podatkov

Ravnanje z risanimi objekti na splošno, vključno z deli modela objektov, ki preživijo povratne poteze nedotaknjene, je pokrito v članku o grafikonih, slikah in risbah

Kje to pusti strežniško namestitev

Če upodabljate delovne zvezke, naložene s strani uporabnikov, v storitvi, je praktični položaj zdaj obranljiv: slike metafila so razčlenjene s kodo, ki jo lahko revizirate, omejene s konstantami, ki jih lahko berete, in nikoli izročene grafičnemu gonilniku. Pošten pridržek je pokritost. Kompleksni metafile, proizvedeni s strani orodij risanja, bodo zadeli števec preskočenih zapisov in odgovor na to je izpostaviti števec namesto tihe širitve belega seznama. Slika, ki se upodobi delno in to pove, je pogovor s podporo; slika, ki se upodobi napačno in ne pove ničesar, je poročilo o hrošču od stranke

HotXLS obravnava XLS, XLSX, ODS in CSV domače v Delphi in C++Builder brez nameščenega Excela in ista filozofija omejene razčlenitve teče skozi njegove plasti vsebnika, formul in risanja. Podrobnosti oblike in varnosti so navedene na strani produkta HotXLS Delphi spreadsheet component