Techninis straipsnis

Nepatikimų EMF ir WMF saugus atkūrimas HotXLS

Excel darbo knyga gali nešti EMF ir WMF paveikslėlius, ir įprastas būdas vieną piešti yra perduoti baitų srautą operacinės sistemos metafailų grotuvui. Tas sprendimas verta žiūrėti tiesiai: metafailas yra serijizuota grafikos API komandų srautas, o jo atkūrimas reiškia, kad el. paštu atkeliavęs failas valdo grafikos tvarkyklę. HotXLS eina kitu keliu. XLSDecodeVectorScene pati analizuoja metafailą, tikrina antraštę, kiekvieną įrašo dydį, deklaruotą įrašų visumą ir tikslų failo pabaigos įrašo išdėstymą, kategoriškai atmeta escape įrašus ir grąžina TXLSVectorScene su pirminėmis braižymo komandomis, kurias Canvas ir SVG posistemiai atkuria per savą kodą. Jokio tvarkyklės atkūrimo nėra nė viename taške

HotXLS analizuoja nepatikimus EMF ir WMF darbalapio baitus su XLSDecodeVectorScene į TXLSVectorScene komandų sąrašą vietoj GDI metafailų atkūrimo
HotXLS pati analizuoja metafailą ir grąžina pirmines komandas Canvas ir SVG atkūrimui; įprastas kelias vykdo baitų srautą grafikos krūvoje

Sandauga yra dengimas už izoliaciją. Stačiakampių orientuota komandų baltoji sąrašo dalis neatkurs kiekvieno dizainerio sukuriamo metafailo, todėl scena praneša, kiek braižymo įrašų ji negalėjo atvaizduoti, o iškviečiantysis nusprendžia, ką dėl to daryti. Serverio procesui, atvaizduojančiam dokumentus, kurių jis pats nesukūrė, ta sandauga yra teisinga kryptimi

Kodėl metafailų atkūrimas netinka nepatikimai įvečiai?

Nes formatas nėra paveikslas — jis yra programa. EMF įrašų srautas valdo įrenginio konteksto būsenų krūvą, išskiria ir pasirenka objektus iš rankenėlių lentelės ir gali nešti escape įrašus, kurių turinys perduodamas įrenginio tvarkyklei. Jo atkūrimas pratina kelius platformos grafikos krūvoje, parašytus manydami, kad metafailas atkeliavo iš bendradarbiaujančios tos pačios mašinos programos. Kai įvestis yra skaičiuoklės priedas, ta prielaida dingsta, ir jokios atsargybės skaičiuoklės bibliotekoje nepadeda, nes biblioteka nėra komponentė, atliekanti analizavimą

Tas pats samprotavimas valdo konteinerio sluoksnį. Darbo knyga yra ZIP archyvas, ir HotXLS tikrina jos centrinį katalogą, o ne pasitiki deklaruotais poslinkiais, kaip aprašyta ZIP centrinio katalogo pabaigos tikrinimo straipsnyje. Metafailų turiniai yra kita tos pačios problemos sluoksnis

Ką dekoderis patikrina prieš piešdamas bet ką

Patikra yra struktūrinė ir vyksta iš anksto, nes analizatorius, pradedantis piešti ir tikrinantis einant, jau yra veikęs pagal duomenis, kurių nepatvirtino. Antraštė privalo atitikti griežtai, o ne tikėtinai. Kiekvienas įrašas privalo deklaruoti dydį, telpantį likusiame buferyje ir pakankamai didelį savo fiksuotiems laukams. Įrašų skaičius, kurį deklaruoja antraštė, privalo atitikti faktiškai esančius įrašus. Failo pabaigos įrašas privalo sėdėti tiksliai ten, kur baigiasi srautas, o ne tik kažkur netoli — tai uždaro galinio šiukšlių gudrybę, slepiančią antrą turinį už teisėto paveikslo

Už struktūros dekoderis yra saugiai nepavykstantis semantikoje. Escape įrašai atmetami, o ne praleidžiami. Būseną keičiantis įrašas, kurio dekoderis nemodeliuoja, priverčia dekodavimą nepavykti, o ne būti ignoruotam, nes būsenos pokyčio ignoravimas reiškia, kad kiekviena tolesnė braižymo komanda vykdoma būsenoje, kurios failas neprašė, o rezultatas yra paveikslas, neteisingas taip, kaip niekas negali nuspėti. Braižymo įrašai už palaikomų komandų rinkinio ribų yra kitas reikalas: tie skaičiuojami ir praleidžiami, nes dingusi forma yra matoma, pranešama spraga, o ne tyli sugadinimas

XLSDecodeVectorScene iš anksto tikrina antraštę, įrašų dydžius, visumas ir EOF išdėstymą, tada atmeta escape įrašus ir skaičiuoja nepalaikomus braižymo įrašus
Struktūrinės patikros vyksta iš anksto, o saugiai nepavykstanti semantika atmeta escape įrašus, o nepalaikomi braižymo įrašai tik skaičiuojami ir praleidžiami

Biudžetai yra formato sutarties dalis

Vektoriniai formatai turi savo išglaudinimo bombos versiją. Keli kilobaitai įrašų gali deklaruoti polilinijas su šimtais milijonų taškų arba atvaizdą, kurio deklaruoti matmenys sudaugėja į terabaitus. Ribos todėl turi būti aiškios konstantos, o ne tai, ką mašina atsitiktinai išgyvena

// Iš lxVectorScene: dekodavimo biudžetas, išsakyta, o ne numanyta
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;

Dvi iš jų nusipelno pastabos. Įrenginio konteksto gylio riba 32 egzistuoja todėl, kad SaveDC ir RestoreDC įrašai vidiniai, o nesubalansuotas srautas gali stumti amžinai; 32 yra dosnu tikriems metafailams ir pigu priverstinai taikyti. Koordinačių riba egzistuoja todėl, kad koordinatės maitina transformaciją, o reikšmė prie sveikųjų intervalo ribų duoda transformuotą rezultatą, kuris arba begalinis, arba apsiverčia, po ko kiekvienas tolesnis ribinio langelio skaičiavimas yra beprasmis. Koordinačių ribojimas analizės metu daug lengviau suvokiamas nei kiekvieno geometrijos vartotojo gynyba

Dekodavimo biudžeto konstantos HotXLS lxVectorScene įrašams, rankenėlėms, DC giliui, komandoms, taškams, tekstui, atvaizdo dydžiui ir koordinačių ribojimui
Kiekviena riba yra įvardyta konstanta, priverstinai taikoma analizės metu; DC gylio riba ir koordinačių ribojimas nusipelno daugiausia dėmesio

Scenos naudojimas

Dekoderis grąžina objektą, kuris priklausys jums, komandų skaičių, vardinį dydį ir braižymo įrašų, kurių nusprendė neatvaizduoti, skaičių

uses
  lxVectorScene;

var
  Scene: TXLSVectorScene;
  Error: WideString;
  I: Integer;
begin
  // Data laiko žalią paveikslo turinį, paimtą iš darbo knygos
  if not XLSDecodeVectorScene(Data, xlsvfEmf, Scene, Error) then
  begin
    // Atmesta: antraštė, ribos, visumos, EOF išdėstymas arba biudžetas
    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;

Komandų įrašas neša viską, ko reikia posistemiui, ir nieko, kas reikalautų įrenginio: pieštuko buvimą, spalvą, storį ir stilių; teptuko buvimą ir spalvą; geometriją; o tekstui — eilutę, šrifto vardą, dydį, stilius ir lygiavimą. Būtent todėl ta pati scena naudotina ir ekrano drobės atvaizduotojo, ir SVG rašyklio, ir todėl vektorinis kelias nesiskiria tarp peržiūros ir eksporto. Darbalapio turinio atvaizdavimas ekrane apskritai dengiamas pasirinktinio VCL tinklelio atvaizdavimo straipsnyje

Paveikslo atmetimas nesugadina darbo knygos

Svarbi šio projekto savybė yra ta, kad atmestas dekodavimas veikia tik atvaizdavimą. Pradinis turinys lieka modelyje, todėl darbo knyga, atidaryta ir vėl įrašyta, išneša savo metafailo paveikslėlius baitas po baito, ar saugus dekoderis galėjo juos piešti, ar ne. Esamas ribotas rastrinis kelias taip pat lieka prieinamas kaip atsarga. Kitaip tariant, griežtas analizatorius užtveria tai, kas vykdoma, o ne tai, kas išsaugoma — ta išskirtis leidžia saugumo motyvuotam pakeitimui išvykti nesivertus duomenų praradimo pakeitimu

Braižymo objektų tvarkymas apskritai, įskaitant objektų modelio dalis, išgyvenančias abipusius perėjimus nepaliestas, dengiamas diagramų, atvaizdų ir braižinių straipsnyje

Kur tai palieka serverio diegimą

Jeigu atvaizduojate vartotojų įkeliamas darbo knygas tarnyboje, praktinė padėtis dabar ginama: metafailo paveikslėliai analizuojami kodo, kurį galite audituoti, ribojami konstantų, kurias galite skaityti, ir niekada neperduodami grafikos tvarkyklei. Sąžininga išlyga yra dengimas. Kompleksiški braižymo įrankių pagaminti metafailai pasieks praleistų įrašų skaitiklį, o atsakymas į tai — iškelti skaitiklį į viršų, o ne tyliai platinti baltąjį sąrašą. Paveikslas, atvaizduotas iš dalies ir tai pasakantis, yra palaikymo pokalbis; paveikslas, atvaizduotas neteisingai ir nieko nesakantis, yra kliento klaidos pranešimas

HotXLS tvarko XLS, XLSX, ODS ir CSV savai Delphi ir C++Builder aplinkose be įdiegto Excel, ir ta pati ribotos analizės filosofia eina per jo konteinerio, formulių ir braižymo sluoksnius. Formato ir saugumo detalės išvardytos HotXLS Delphi spreadsheet component produkto puslapyje