| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447 |
- /*
- * Copyright (c) 1988-1997 Sam Leffler
- * Copyright (c) 1991-1997 Silicon Graphics, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and
- * its documentation for any purpose is hereby granted without fee, provided
- * that (i) the above copyright notices and this permission notice appear in
- * all copies of the software and related documentation, and (ii) the names of
- * Sam Leffler and Silicon Graphics may not be used in any advertising or
- * publicity relating to the software without the specific, prior written
- * permission of Sam Leffler and Silicon Graphics.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
- * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
- * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
- * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
- /*
- * TIFF Library.
- *
- * Directory Read Support Routines.
- */
- /* Suggested pending improvements:
- * - add a field 'field_info' to the TIFFDirEntry structure, and set that with
- * the pointer to the appropriate TIFFField structure early on in
- * TIFFReadDirectory, so as to eliminate current possibly repetitive lookup.
- */
- #include "tiffconf.h"
- #include "tiffiop.h"
- #include <float.h>
- #include <limits.h>
- #include <stdlib.h>
- #include <string.h>
- #define FAILED_FII ((uint32_t)-1)
- #ifdef HAVE_IEEEFP
- #define TIFFCvtIEEEFloatToNative(tif, n, fp)
- #define TIFFCvtIEEEDoubleToNative(tif, n, dp)
- #else
- /* If your machine does not support IEEE floating point then you will need to
- * add support to tif_machdep.c to convert between the native format and
- * IEEE format. */
- extern void TIFFCvtIEEEFloatToNative(TIFF *, uint32_t, float *);
- extern void TIFFCvtIEEEDoubleToNative(TIFF *, uint32_t, double *);
- #endif
- enum TIFFReadDirEntryErr
- {
- TIFFReadDirEntryErrOk = 0,
- TIFFReadDirEntryErrCount = 1,
- TIFFReadDirEntryErrType = 2,
- TIFFReadDirEntryErrIo = 3,
- TIFFReadDirEntryErrRange = 4,
- TIFFReadDirEntryErrPsdif = 5,
- TIFFReadDirEntryErrSizesan = 6,
- TIFFReadDirEntryErrAlloc = 7,
- };
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryByte(TIFF *tif, TIFFDirEntry *direntry, uint8_t *value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntrySbyte(TIFF *tif, TIFFDirEntry *direntry, int8_t *value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryShort(TIFF *tif, TIFFDirEntry *direntry, uint16_t *value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntrySshort(TIFF *tif, TIFFDirEntry *direntry, int16_t *value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryLong(TIFF *tif, TIFFDirEntry *direntry, uint32_t *value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntrySlong(TIFF *tif, TIFFDirEntry *direntry, int32_t *value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryLong8(TIFF *tif, TIFFDirEntry *direntry, uint64_t *value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntrySlong8(TIFF *tif, TIFFDirEntry *direntry, int64_t *value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryFloat(TIFF *tif, TIFFDirEntry *direntry, float *value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryDouble(TIFF *tif, TIFFDirEntry *direntry, double *value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryIfd8(TIFF *tif, TIFFDirEntry *direntry, uint64_t *value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryArray(TIFF *tif, TIFFDirEntry *direntry, uint32_t *count,
- uint32_t desttypesize, void **value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryByteArray(TIFF *tif, TIFFDirEntry *direntry, uint8_t **value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntrySbyteArray(TIFF *tif, TIFFDirEntry *direntry, int8_t **value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryShortArray(TIFF *tif, TIFFDirEntry *direntry, uint16_t **value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntrySshortArray(TIFF *tif, TIFFDirEntry *direntry, int16_t **value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryLongArray(TIFF *tif, TIFFDirEntry *direntry, uint32_t **value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntrySlongArray(TIFF *tif, TIFFDirEntry *direntry, int32_t **value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryLong8Array(TIFF *tif, TIFFDirEntry *direntry, uint64_t **value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntrySlong8Array(TIFF *tif, TIFFDirEntry *direntry, int64_t **value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryFloatArray(TIFF *tif, TIFFDirEntry *direntry, float **value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryDoubleArray(TIFF *tif, TIFFDirEntry *direntry, double **value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryIfd8Array(TIFF *tif, TIFFDirEntry *direntry, uint64_t **value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryPersampleShort(TIFF *tif, TIFFDirEntry *direntry,
- uint16_t *value);
- static void TIFFReadDirEntryCheckedByte(TIFF *tif, TIFFDirEntry *direntry,
- uint8_t *value);
- static void TIFFReadDirEntryCheckedSbyte(TIFF *tif, TIFFDirEntry *direntry,
- int8_t *value);
- static void TIFFReadDirEntryCheckedShort(TIFF *tif, TIFFDirEntry *direntry,
- uint16_t *value);
- static void TIFFReadDirEntryCheckedSshort(TIFF *tif, TIFFDirEntry *direntry,
- int16_t *value);
- static void TIFFReadDirEntryCheckedLong(TIFF *tif, TIFFDirEntry *direntry,
- uint32_t *value);
- static void TIFFReadDirEntryCheckedSlong(TIFF *tif, TIFFDirEntry *direntry,
- int32_t *value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckedLong8(TIFF *tif, TIFFDirEntry *direntry,
- uint64_t *value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckedSlong8(TIFF *tif, TIFFDirEntry *direntry,
- int64_t *value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckedRational(TIFF *tif, TIFFDirEntry *direntry,
- double *value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckedSrational(TIFF *tif, TIFFDirEntry *direntry,
- double *value);
- static void TIFFReadDirEntryCheckedFloat(TIFF *tif, TIFFDirEntry *direntry,
- float *value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckedDouble(TIFF *tif, TIFFDirEntry *direntry, double *value);
- #if 0
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckedRationalDirect(TIFF *tif, TIFFDirEntry *direntry,
- TIFFRational_t *value);
- #endif
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeByteSbyte(int8_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeByteShort(uint16_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeByteSshort(int16_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeByteLong(uint32_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeByteSlong(int32_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeByteLong8(uint64_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeByteSlong8(int64_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSbyteByte(uint8_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSbyteShort(uint16_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSbyteSshort(int16_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSbyteLong(uint32_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSbyteSlong(int32_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSbyteLong8(uint64_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSbyteSlong8(int64_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeShortSbyte(int8_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeShortSshort(int16_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeShortLong(uint32_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeShortSlong(int32_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeShortLong8(uint64_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeShortSlong8(int64_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSshortShort(uint16_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSshortLong(uint32_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSshortSlong(int32_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSshortLong8(uint64_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSshortSlong8(int64_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeLongSbyte(int8_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeLongSshort(int16_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeLongSlong(int32_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeLongLong8(uint64_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeLongSlong8(int64_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSlongLong(uint32_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSlongLong8(uint64_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSlongSlong8(int64_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeLong8Sbyte(int8_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeLong8Sshort(int16_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeLong8Slong(int32_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeLong8Slong8(int64_t value);
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSlong8Long8(uint64_t value);
- static enum TIFFReadDirEntryErr TIFFReadDirEntryData(TIFF *tif, uint64_t offset,
- tmsize_t size, void *dest);
- static void TIFFReadDirEntryOutputErr(TIFF *tif, enum TIFFReadDirEntryErr err,
- const char *module, const char *tagname,
- int recover);
- static void TIFFReadDirectoryCheckOrder(TIFF *tif, TIFFDirEntry *dir,
- uint16_t dircount);
- static TIFFDirEntry *TIFFReadDirectoryFindEntry(TIFF *tif, TIFFDirEntry *dir,
- uint16_t dircount,
- uint16_t tagid);
- static void TIFFReadDirectoryFindFieldInfo(TIFF *tif, uint16_t tagid,
- uint32_t *fii);
- static int EstimateStripByteCounts(TIFF *tif, TIFFDirEntry *dir,
- uint16_t dircount);
- static void MissingRequired(TIFF *, const char *);
- static int CheckDirCount(TIFF *, TIFFDirEntry *, uint32_t);
- static uint16_t TIFFFetchDirectory(TIFF *tif, uint64_t diroff,
- TIFFDirEntry **pdir, uint64_t *nextdiroff);
- static int TIFFFetchNormalTag(TIFF *, TIFFDirEntry *, int recover);
- static int TIFFFetchStripThing(TIFF *tif, TIFFDirEntry *dir, uint32_t nstrips,
- uint64_t **lpp);
- static int TIFFFetchSubjectDistance(TIFF *, TIFFDirEntry *);
- static void ChopUpSingleUncompressedStrip(TIFF *);
- static void TryChopUpUncompressedBigTiff(TIFF *);
- static uint64_t TIFFReadUInt64(const uint8_t *value);
- static int _TIFFGetMaxColorChannels(uint16_t photometric);
- static int _TIFFFillStrilesInternal(TIFF *tif, int loadStripByteCount);
- typedef union _UInt64Aligned_t
- {
- double d;
- uint64_t l;
- uint32_t i[2];
- uint16_t s[4];
- uint8_t c[8];
- } UInt64Aligned_t;
- /*
- Unaligned safe copy of a uint64_t value from an octet array.
- */
- static uint64_t TIFFReadUInt64(const uint8_t *value)
- {
- UInt64Aligned_t result;
- result.c[0] = value[0];
- result.c[1] = value[1];
- result.c[2] = value[2];
- result.c[3] = value[3];
- result.c[4] = value[4];
- result.c[5] = value[5];
- result.c[6] = value[6];
- result.c[7] = value[7];
- return result.l;
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryByte(TIFF *tif, TIFFDirEntry *direntry, uint8_t *value)
- {
- enum TIFFReadDirEntryErr err;
- if (direntry->tdir_count != 1)
- return (TIFFReadDirEntryErrCount);
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- case TIFF_UNDEFINED: /* Support to read TIFF_UNDEFINED with
- field_readcount==1 */
- TIFFReadDirEntryCheckedByte(tif, direntry, value);
- return (TIFFReadDirEntryErrOk);
- case TIFF_SBYTE:
- {
- int8_t m;
- TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeByteSbyte(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint8_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SHORT:
- {
- uint16_t m;
- TIFFReadDirEntryCheckedShort(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeByteShort(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint8_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SSHORT:
- {
- int16_t m;
- TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeByteSshort(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint8_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG:
- {
- uint32_t m;
- TIFFReadDirEntryCheckedLong(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeByteLong(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint8_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG:
- {
- int32_t m;
- TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeByteSlong(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint8_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG8:
- {
- uint64_t m;
- err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- err = TIFFReadDirEntryCheckRangeByteLong8(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint8_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG8:
- {
- int64_t m;
- err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- err = TIFFReadDirEntryCheckRangeByteSlong8(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint8_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- default:
- return (TIFFReadDirEntryErrType);
- }
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntrySbyte(TIFF *tif, TIFFDirEntry *direntry, int8_t *value)
- {
- enum TIFFReadDirEntryErr err;
- if (direntry->tdir_count != 1)
- return (TIFFReadDirEntryErrCount);
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- case TIFF_UNDEFINED: /* Support to read TIFF_UNDEFINED with
- field_readcount==1 */
- {
- uint8_t m;
- TIFFReadDirEntryCheckedByte(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeSbyteByte(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (int8_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SBYTE:
- {
- TIFFReadDirEntryCheckedSbyte(tif, direntry, value);
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SHORT:
- {
- uint16_t m;
- TIFFReadDirEntryCheckedShort(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeSbyteShort(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (int8_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SSHORT:
- {
- int16_t m;
- TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeSbyteSshort(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (int8_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG:
- {
- uint32_t m;
- TIFFReadDirEntryCheckedLong(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeSbyteLong(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (int8_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG:
- {
- int32_t m;
- TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeSbyteSlong(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (int8_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG8:
- {
- uint64_t m;
- err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- err = TIFFReadDirEntryCheckRangeSbyteLong8(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (int8_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG8:
- {
- int64_t m;
- err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- err = TIFFReadDirEntryCheckRangeSbyteSlong8(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (int8_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- default:
- return (TIFFReadDirEntryErrType);
- }
- } /*-- TIFFReadDirEntrySbyte() --*/
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryShort(TIFF *tif, TIFFDirEntry *direntry, uint16_t *value)
- {
- enum TIFFReadDirEntryErr err;
- if (direntry->tdir_count != 1)
- return (TIFFReadDirEntryErrCount);
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- {
- uint8_t m;
- TIFFReadDirEntryCheckedByte(tif, direntry, &m);
- *value = (uint16_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SBYTE:
- {
- int8_t m;
- TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeShortSbyte(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint16_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SHORT:
- TIFFReadDirEntryCheckedShort(tif, direntry, value);
- return (TIFFReadDirEntryErrOk);
- case TIFF_SSHORT:
- {
- int16_t m;
- TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeShortSshort(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint16_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG:
- {
- uint32_t m;
- TIFFReadDirEntryCheckedLong(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeShortLong(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint16_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG:
- {
- int32_t m;
- TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeShortSlong(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint16_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG8:
- {
- uint64_t m;
- err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- err = TIFFReadDirEntryCheckRangeShortLong8(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint16_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG8:
- {
- int64_t m;
- err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- err = TIFFReadDirEntryCheckRangeShortSlong8(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint16_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- default:
- return (TIFFReadDirEntryErrType);
- }
- } /*-- TIFFReadDirEntryShort() --*/
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntrySshort(TIFF *tif, TIFFDirEntry *direntry, int16_t *value)
- {
- enum TIFFReadDirEntryErr err;
- if (direntry->tdir_count != 1)
- return (TIFFReadDirEntryErrCount);
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- {
- uint8_t m;
- TIFFReadDirEntryCheckedByte(tif, direntry, &m);
- *value = (int16_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SBYTE:
- {
- int8_t m;
- TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
- *value = (int16_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SHORT:
- {
- uint16_t m;
- TIFFReadDirEntryCheckedShort(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeSshortShort(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint16_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SSHORT:
- TIFFReadDirEntryCheckedSshort(tif, direntry, value);
- return (TIFFReadDirEntryErrOk);
- case TIFF_LONG:
- {
- uint32_t m;
- TIFFReadDirEntryCheckedLong(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeSshortLong(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (int16_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG:
- {
- int32_t m;
- TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeSshortSlong(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (int16_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG8:
- {
- uint64_t m;
- err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- err = TIFFReadDirEntryCheckRangeSshortLong8(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (int16_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG8:
- {
- int64_t m;
- err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- err = TIFFReadDirEntryCheckRangeSshortSlong8(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (int16_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- default:
- return (TIFFReadDirEntryErrType);
- }
- } /*-- TIFFReadDirEntrySshort() --*/
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryLong(TIFF *tif, TIFFDirEntry *direntry, uint32_t *value)
- {
- enum TIFFReadDirEntryErr err;
- if (direntry->tdir_count != 1)
- return (TIFFReadDirEntryErrCount);
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- {
- uint8_t m;
- TIFFReadDirEntryCheckedByte(tif, direntry, &m);
- *value = (uint32_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SBYTE:
- {
- int8_t m;
- TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeLongSbyte(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint32_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SHORT:
- {
- uint16_t m;
- TIFFReadDirEntryCheckedShort(tif, direntry, &m);
- *value = (uint32_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SSHORT:
- {
- int16_t m;
- TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeLongSshort(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint32_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG:
- TIFFReadDirEntryCheckedLong(tif, direntry, value);
- return (TIFFReadDirEntryErrOk);
- case TIFF_SLONG:
- {
- int32_t m;
- TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeLongSlong(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint32_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG8:
- {
- uint64_t m;
- err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- err = TIFFReadDirEntryCheckRangeLongLong8(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint32_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG8:
- {
- int64_t m;
- err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- err = TIFFReadDirEntryCheckRangeLongSlong8(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint32_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- default:
- return (TIFFReadDirEntryErrType);
- }
- } /*-- TIFFReadDirEntryLong() --*/
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntrySlong(TIFF *tif, TIFFDirEntry *direntry, int32_t *value)
- {
- enum TIFFReadDirEntryErr err;
- if (direntry->tdir_count != 1)
- return (TIFFReadDirEntryErrCount);
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- {
- uint8_t m;
- TIFFReadDirEntryCheckedByte(tif, direntry, &m);
- *value = (int32_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SBYTE:
- {
- int8_t m;
- TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
- *value = (int32_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SHORT:
- {
- uint16_t m;
- TIFFReadDirEntryCheckedShort(tif, direntry, &m);
- *value = (int32_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SSHORT:
- {
- int16_t m;
- TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
- *value = (int32_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG:
- {
- uint32_t m;
- TIFFReadDirEntryCheckedLong(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeSlongLong(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (int32_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG:
- TIFFReadDirEntryCheckedSlong(tif, direntry, value);
- return (TIFFReadDirEntryErrOk);
- case TIFF_LONG8:
- {
- uint64_t m;
- err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- err = TIFFReadDirEntryCheckRangeSlongLong8(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (int32_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG8:
- {
- int64_t m;
- err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- err = TIFFReadDirEntryCheckRangeSlongSlong8(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (int32_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- default:
- return (TIFFReadDirEntryErrType);
- }
- } /*-- TIFFReadDirEntrySlong() --*/
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryLong8(TIFF *tif, TIFFDirEntry *direntry, uint64_t *value)
- {
- enum TIFFReadDirEntryErr err;
- if (direntry->tdir_count != 1)
- return (TIFFReadDirEntryErrCount);
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- {
- uint8_t m;
- TIFFReadDirEntryCheckedByte(tif, direntry, &m);
- *value = (uint64_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SBYTE:
- {
- int8_t m;
- TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeLong8Sbyte(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint64_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SHORT:
- {
- uint16_t m;
- TIFFReadDirEntryCheckedShort(tif, direntry, &m);
- *value = (uint64_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SSHORT:
- {
- int16_t m;
- TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeLong8Sshort(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint64_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG:
- {
- uint32_t m;
- TIFFReadDirEntryCheckedLong(tif, direntry, &m);
- *value = (uint64_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG:
- {
- int32_t m;
- TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
- err = TIFFReadDirEntryCheckRangeLong8Slong(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint64_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG8:
- err = TIFFReadDirEntryCheckedLong8(tif, direntry, value);
- return (err);
- case TIFF_SLONG8:
- {
- int64_t m;
- err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- err = TIFFReadDirEntryCheckRangeLong8Slong8(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (uint64_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- default:
- return (TIFFReadDirEntryErrType);
- }
- } /*-- TIFFReadDirEntryLong8() --*/
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntrySlong8(TIFF *tif, TIFFDirEntry *direntry, int64_t *value)
- {
- enum TIFFReadDirEntryErr err;
- if (direntry->tdir_count != 1)
- return (TIFFReadDirEntryErrCount);
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- {
- uint8_t m;
- TIFFReadDirEntryCheckedByte(tif, direntry, &m);
- *value = (int64_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SBYTE:
- {
- int8_t m;
- TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
- *value = (int64_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SHORT:
- {
- uint16_t m;
- TIFFReadDirEntryCheckedShort(tif, direntry, &m);
- *value = (int64_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SSHORT:
- {
- int16_t m;
- TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
- *value = (int64_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG:
- {
- uint32_t m;
- TIFFReadDirEntryCheckedLong(tif, direntry, &m);
- *value = (int64_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG:
- {
- int32_t m;
- TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
- *value = (int64_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG8:
- {
- uint64_t m;
- err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- err = TIFFReadDirEntryCheckRangeSlong8Long8(m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (int64_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG8:
- err = TIFFReadDirEntryCheckedSlong8(tif, direntry, value);
- return (err);
- default:
- return (TIFFReadDirEntryErrType);
- }
- } /*-- TIFFReadDirEntrySlong8() --*/
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryFloat(TIFF *tif, TIFFDirEntry *direntry, float *value)
- {
- enum TIFFReadDirEntryErr err;
- if (direntry->tdir_count != 1)
- return (TIFFReadDirEntryErrCount);
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- {
- uint8_t m;
- TIFFReadDirEntryCheckedByte(tif, direntry, &m);
- *value = (float)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SBYTE:
- {
- int8_t m;
- TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
- *value = (float)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SHORT:
- {
- uint16_t m;
- TIFFReadDirEntryCheckedShort(tif, direntry, &m);
- *value = (float)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SSHORT:
- {
- int16_t m;
- TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
- *value = (float)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG:
- {
- uint32_t m;
- TIFFReadDirEntryCheckedLong(tif, direntry, &m);
- *value = (float)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG:
- {
- int32_t m;
- TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
- *value = (float)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG8:
- {
- uint64_t m;
- err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (float)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG8:
- {
- int64_t m;
- err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (float)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_RATIONAL:
- {
- double m;
- err = TIFFReadDirEntryCheckedRational(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (float)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SRATIONAL:
- {
- double m;
- err = TIFFReadDirEntryCheckedSrational(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (float)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_FLOAT:
- TIFFReadDirEntryCheckedFloat(tif, direntry, value);
- return (TIFFReadDirEntryErrOk);
- case TIFF_DOUBLE:
- {
- double m;
- err = TIFFReadDirEntryCheckedDouble(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- if ((m > FLT_MAX) || (m < -FLT_MAX))
- return (TIFFReadDirEntryErrRange);
- *value = (float)m;
- return (TIFFReadDirEntryErrOk);
- }
- default:
- return (TIFFReadDirEntryErrType);
- }
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryDouble(TIFF *tif, TIFFDirEntry *direntry, double *value)
- {
- enum TIFFReadDirEntryErr err;
- if (direntry->tdir_count != 1)
- return (TIFFReadDirEntryErrCount);
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- {
- uint8_t m;
- TIFFReadDirEntryCheckedByte(tif, direntry, &m);
- *value = (double)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SBYTE:
- {
- int8_t m;
- TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
- *value = (double)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SHORT:
- {
- uint16_t m;
- TIFFReadDirEntryCheckedShort(tif, direntry, &m);
- *value = (double)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SSHORT:
- {
- int16_t m;
- TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
- *value = (double)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG:
- {
- uint32_t m;
- TIFFReadDirEntryCheckedLong(tif, direntry, &m);
- *value = (double)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG:
- {
- int32_t m;
- TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
- *value = (double)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG8:
- {
- uint64_t m;
- err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (double)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG8:
- {
- int64_t m;
- err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- *value = (double)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_RATIONAL:
- err = TIFFReadDirEntryCheckedRational(tif, direntry, value);
- return (err);
- case TIFF_SRATIONAL:
- err = TIFFReadDirEntryCheckedSrational(tif, direntry, value);
- return (err);
- case TIFF_FLOAT:
- {
- float m;
- TIFFReadDirEntryCheckedFloat(tif, direntry, &m);
- *value = (double)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_DOUBLE:
- err = TIFFReadDirEntryCheckedDouble(tif, direntry, value);
- return (err);
- default:
- return (TIFFReadDirEntryErrType);
- }
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryIfd8(TIFF *tif, TIFFDirEntry *direntry, uint64_t *value)
- {
- enum TIFFReadDirEntryErr err;
- if (direntry->tdir_count != 1)
- return (TIFFReadDirEntryErrCount);
- switch (direntry->tdir_type)
- {
- case TIFF_LONG:
- case TIFF_IFD:
- {
- uint32_t m;
- TIFFReadDirEntryCheckedLong(tif, direntry, &m);
- *value = (uint64_t)m;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_LONG8:
- case TIFF_IFD8:
- err = TIFFReadDirEntryCheckedLong8(tif, direntry, value);
- return (err);
- default:
- return (TIFFReadDirEntryErrType);
- }
- }
- #define INITIAL_THRESHOLD (1024 * 1024)
- #define THRESHOLD_MULTIPLIER 10
- #define MAX_THRESHOLD \
- (THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * \
- INITIAL_THRESHOLD)
- static enum TIFFReadDirEntryErr TIFFReadDirEntryDataAndRealloc(TIFF *tif,
- uint64_t offset,
- tmsize_t size,
- void **pdest)
- {
- #if SIZEOF_SIZE_T == 8
- tmsize_t threshold = INITIAL_THRESHOLD;
- #endif
- tmsize_t already_read = 0;
- assert(!isMapped(tif));
- if (!SeekOK(tif, offset))
- return (TIFFReadDirEntryErrIo);
- /* On 64 bit processes, read first a maximum of 1 MB, then 10 MB, etc */
- /* so as to avoid allocating too much memory in case the file is too */
- /* short. We could ask for the file size, but this might be */
- /* expensive with some I/O layers (think of reading a gzipped file) */
- /* Restrict to 64 bit processes, so as to avoid reallocs() */
- /* on 32 bit processes where virtual memory is scarce. */
- while (already_read < size)
- {
- void *new_dest;
- tmsize_t bytes_read;
- tmsize_t to_read = size - already_read;
- #if SIZEOF_SIZE_T == 8
- if (to_read >= threshold && threshold < MAX_THRESHOLD)
- {
- to_read = threshold;
- threshold *= THRESHOLD_MULTIPLIER;
- }
- #endif
- new_dest =
- (uint8_t *)_TIFFreallocExt(tif, *pdest, already_read + to_read);
- if (new_dest == NULL)
- {
- TIFFErrorExtR(tif, tif->tif_name,
- "Failed to allocate memory for %s "
- "(%" TIFF_SSIZE_FORMAT
- " elements of %" TIFF_SSIZE_FORMAT " bytes each)",
- "TIFFReadDirEntryArray", (tmsize_t)1,
- already_read + to_read);
- return TIFFReadDirEntryErrAlloc;
- }
- *pdest = new_dest;
- bytes_read = TIFFReadFile(tif, (char *)*pdest + already_read, to_read);
- already_read += bytes_read;
- if (bytes_read != to_read)
- {
- return TIFFReadDirEntryErrIo;
- }
- }
- return TIFFReadDirEntryErrOk;
- }
- /* Caution: if raising that value, make sure int32 / uint32 overflows can't
- * occur elsewhere */
- #define MAX_SIZE_TAG_DATA 2147483647U
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryArrayWithLimit(TIFF *tif, TIFFDirEntry *direntry,
- uint32_t *count, uint32_t desttypesize,
- void **value, uint64_t maxcount)
- {
- int typesize;
- uint32_t datasize;
- void *data;
- uint64_t target_count64;
- int original_datasize_clamped;
- typesize = TIFFDataWidth(direntry->tdir_type);
- target_count64 =
- (direntry->tdir_count > maxcount) ? maxcount : direntry->tdir_count;
- if ((target_count64 == 0) || (typesize == 0))
- {
- *value = 0;
- return (TIFFReadDirEntryErrOk);
- }
- (void)desttypesize;
- /* We just want to know if the original tag size is more than 4 bytes
- * (classic TIFF) or 8 bytes (BigTIFF)
- */
- original_datasize_clamped =
- ((direntry->tdir_count > 10) ? 10 : (int)direntry->tdir_count) *
- typesize;
- /*
- * As a sanity check, make sure we have no more than a 2GB tag array
- * in either the current data type or the dest data type. This also
- * avoids problems with overflow of tmsize_t on 32bit systems.
- */
- if ((uint64_t)(MAX_SIZE_TAG_DATA / typesize) < target_count64)
- return (TIFFReadDirEntryErrSizesan);
- if ((uint64_t)(MAX_SIZE_TAG_DATA / desttypesize) < target_count64)
- return (TIFFReadDirEntryErrSizesan);
- *count = (uint32_t)target_count64;
- datasize = (*count) * typesize;
- assert((tmsize_t)datasize > 0);
- if (datasize > 100 * 1024 * 1024)
- {
- /* Before allocating a huge amount of memory for corrupted files, check
- * if size of requested memory is not greater than file size.
- */
- const uint64_t filesize = TIFFGetFileSize(tif);
- if (datasize > filesize)
- {
- TIFFWarningExtR(tif, "ReadDirEntryArray",
- "Requested memory size for tag %d (0x%x) %" PRIu32
- " is greater than filesize %" PRIu64
- ". Memory not allocated, tag not read",
- direntry->tdir_tag, direntry->tdir_tag, datasize,
- filesize);
- return (TIFFReadDirEntryErrAlloc);
- }
- }
- if (isMapped(tif) && datasize > (uint64_t)tif->tif_size)
- return TIFFReadDirEntryErrIo;
- if (!isMapped(tif) && (((tif->tif_flags & TIFF_BIGTIFF) && datasize > 8) ||
- (!(tif->tif_flags & TIFF_BIGTIFF) && datasize > 4)))
- {
- data = NULL;
- }
- else
- {
- data = _TIFFCheckMalloc(tif, *count, typesize, "ReadDirEntryArray");
- if (data == 0)
- return (TIFFReadDirEntryErrAlloc);
- }
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- /* Only the condition on original_datasize_clamped. The second
- * one is implied, but Coverity Scan cannot see it. */
- if (original_datasize_clamped <= 4 && datasize <= 4)
- _TIFFmemcpy(data, &direntry->tdir_offset, datasize);
- else
- {
- enum TIFFReadDirEntryErr err;
- uint32_t offset = direntry->tdir_offset.toff_long;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&offset);
- if (isMapped(tif))
- err = TIFFReadDirEntryData(tif, (uint64_t)offset,
- (tmsize_t)datasize, data);
- else
- err = TIFFReadDirEntryDataAndRealloc(tif, (uint64_t)offset,
- (tmsize_t)datasize, &data);
- if (err != TIFFReadDirEntryErrOk)
- {
- _TIFFfreeExt(tif, data);
- return (err);
- }
- }
- }
- else
- {
- /* See above comment for the Classic TIFF case */
- if (original_datasize_clamped <= 8 && datasize <= 8)
- _TIFFmemcpy(data, &direntry->tdir_offset, datasize);
- else
- {
- enum TIFFReadDirEntryErr err;
- uint64_t offset = direntry->tdir_offset.toff_long8;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(&offset);
- if (isMapped(tif))
- err = TIFFReadDirEntryData(tif, (uint64_t)offset,
- (tmsize_t)datasize, data);
- else
- err = TIFFReadDirEntryDataAndRealloc(tif, (uint64_t)offset,
- (tmsize_t)datasize, &data);
- if (err != TIFFReadDirEntryErrOk)
- {
- _TIFFfreeExt(tif, data);
- return (err);
- }
- }
- }
- *value = data;
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryArray(TIFF *tif, TIFFDirEntry *direntry, uint32_t *count,
- uint32_t desttypesize, void **value)
- {
- return TIFFReadDirEntryArrayWithLimit(tif, direntry, count, desttypesize,
- value, ~((uint64_t)0));
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryByteArray(TIFF *tif, TIFFDirEntry *direntry, uint8_t **value)
- {
- enum TIFFReadDirEntryErr err;
- uint32_t count;
- void *origdata;
- uint8_t *data;
- switch (direntry->tdir_type)
- {
- case TIFF_ASCII:
- case TIFF_UNDEFINED:
- case TIFF_BYTE:
- case TIFF_SBYTE:
- case TIFF_SHORT:
- case TIFF_SSHORT:
- case TIFF_LONG:
- case TIFF_SLONG:
- case TIFF_LONG8:
- case TIFF_SLONG8:
- break;
- default:
- return (TIFFReadDirEntryErrType);
- }
- err = TIFFReadDirEntryArray(tif, direntry, &count, 1, &origdata);
- if ((err != TIFFReadDirEntryErrOk) || (origdata == 0))
- {
- *value = 0;
- return (err);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_ASCII:
- case TIFF_UNDEFINED:
- case TIFF_BYTE:
- *value = (uint8_t *)origdata;
- return (TIFFReadDirEntryErrOk);
- case TIFF_SBYTE:
- {
- int8_t *m;
- uint32_t n;
- m = (int8_t *)origdata;
- for (n = 0; n < count; n++)
- {
- err = TIFFReadDirEntryCheckRangeByteSbyte(*m);
- if (err != TIFFReadDirEntryErrOk)
- {
- _TIFFfreeExt(tif, origdata);
- return (err);
- }
- m++;
- }
- *value = (uint8_t *)origdata;
- return (TIFFReadDirEntryErrOk);
- }
- }
- data = (uint8_t *)_TIFFmallocExt(tif, count);
- if (data == 0)
- {
- _TIFFfreeExt(tif, origdata);
- return (TIFFReadDirEntryErrAlloc);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_SHORT:
- {
- uint16_t *ma;
- uint8_t *mb;
- uint32_t n;
- ma = (uint16_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(ma);
- err = TIFFReadDirEntryCheckRangeByteShort(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (uint8_t)(*ma++);
- }
- }
- break;
- case TIFF_SSHORT:
- {
- int16_t *ma;
- uint8_t *mb;
- uint32_t n;
- ma = (int16_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((uint16_t *)ma);
- err = TIFFReadDirEntryCheckRangeByteSshort(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (uint8_t)(*ma++);
- }
- }
- break;
- case TIFF_LONG:
- {
- uint32_t *ma;
- uint8_t *mb;
- uint32_t n;
- ma = (uint32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(ma);
- err = TIFFReadDirEntryCheckRangeByteLong(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (uint8_t)(*ma++);
- }
- }
- break;
- case TIFF_SLONG:
- {
- int32_t *ma;
- uint8_t *mb;
- uint32_t n;
- ma = (int32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong((uint32_t *)ma);
- err = TIFFReadDirEntryCheckRangeByteSlong(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (uint8_t)(*ma++);
- }
- }
- break;
- case TIFF_LONG8:
- {
- uint64_t *ma;
- uint8_t *mb;
- uint32_t n;
- ma = (uint64_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(ma);
- err = TIFFReadDirEntryCheckRangeByteLong8(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (uint8_t)(*ma++);
- }
- }
- break;
- case TIFF_SLONG8:
- {
- int64_t *ma;
- uint8_t *mb;
- uint32_t n;
- ma = (int64_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8((uint64_t *)ma);
- err = TIFFReadDirEntryCheckRangeByteSlong8(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (uint8_t)(*ma++);
- }
- }
- break;
- }
- _TIFFfreeExt(tif, origdata);
- if (err != TIFFReadDirEntryErrOk)
- {
- _TIFFfreeExt(tif, data);
- return (err);
- }
- *value = data;
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntrySbyteArray(TIFF *tif, TIFFDirEntry *direntry, int8_t **value)
- {
- enum TIFFReadDirEntryErr err;
- uint32_t count;
- void *origdata;
- int8_t *data;
- switch (direntry->tdir_type)
- {
- case TIFF_UNDEFINED:
- case TIFF_BYTE:
- case TIFF_SBYTE:
- case TIFF_SHORT:
- case TIFF_SSHORT:
- case TIFF_LONG:
- case TIFF_SLONG:
- case TIFF_LONG8:
- case TIFF_SLONG8:
- break;
- default:
- return (TIFFReadDirEntryErrType);
- }
- err = TIFFReadDirEntryArray(tif, direntry, &count, 1, &origdata);
- if ((err != TIFFReadDirEntryErrOk) || (origdata == 0))
- {
- *value = 0;
- return (err);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_UNDEFINED:
- case TIFF_BYTE:
- {
- uint8_t *m;
- uint32_t n;
- m = (uint8_t *)origdata;
- for (n = 0; n < count; n++)
- {
- err = TIFFReadDirEntryCheckRangeSbyteByte(*m);
- if (err != TIFFReadDirEntryErrOk)
- {
- _TIFFfreeExt(tif, origdata);
- return (err);
- }
- m++;
- }
- *value = (int8_t *)origdata;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SBYTE:
- *value = (int8_t *)origdata;
- return (TIFFReadDirEntryErrOk);
- }
- data = (int8_t *)_TIFFmallocExt(tif, count);
- if (data == 0)
- {
- _TIFFfreeExt(tif, origdata);
- return (TIFFReadDirEntryErrAlloc);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_SHORT:
- {
- uint16_t *ma;
- int8_t *mb;
- uint32_t n;
- ma = (uint16_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(ma);
- err = TIFFReadDirEntryCheckRangeSbyteShort(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (int8_t)(*ma++);
- }
- }
- break;
- case TIFF_SSHORT:
- {
- int16_t *ma;
- int8_t *mb;
- uint32_t n;
- ma = (int16_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((uint16_t *)ma);
- err = TIFFReadDirEntryCheckRangeSbyteSshort(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (int8_t)(*ma++);
- }
- }
- break;
- case TIFF_LONG:
- {
- uint32_t *ma;
- int8_t *mb;
- uint32_t n;
- ma = (uint32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(ma);
- err = TIFFReadDirEntryCheckRangeSbyteLong(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (int8_t)(*ma++);
- }
- }
- break;
- case TIFF_SLONG:
- {
- int32_t *ma;
- int8_t *mb;
- uint32_t n;
- ma = (int32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong((uint32_t *)ma);
- err = TIFFReadDirEntryCheckRangeSbyteSlong(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (int8_t)(*ma++);
- }
- }
- break;
- case TIFF_LONG8:
- {
- uint64_t *ma;
- int8_t *mb;
- uint32_t n;
- ma = (uint64_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(ma);
- err = TIFFReadDirEntryCheckRangeSbyteLong8(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (int8_t)(*ma++);
- }
- }
- break;
- case TIFF_SLONG8:
- {
- int64_t *ma;
- int8_t *mb;
- uint32_t n;
- ma = (int64_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8((uint64_t *)ma);
- err = TIFFReadDirEntryCheckRangeSbyteSlong8(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (int8_t)(*ma++);
- }
- }
- break;
- }
- _TIFFfreeExt(tif, origdata);
- if (err != TIFFReadDirEntryErrOk)
- {
- _TIFFfreeExt(tif, data);
- return (err);
- }
- *value = data;
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryShortArray(TIFF *tif, TIFFDirEntry *direntry, uint16_t **value)
- {
- enum TIFFReadDirEntryErr err;
- uint32_t count;
- void *origdata;
- uint16_t *data;
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- case TIFF_SBYTE:
- case TIFF_SHORT:
- case TIFF_SSHORT:
- case TIFF_LONG:
- case TIFF_SLONG:
- case TIFF_LONG8:
- case TIFF_SLONG8:
- break;
- default:
- return (TIFFReadDirEntryErrType);
- }
- err = TIFFReadDirEntryArray(tif, direntry, &count, 2, &origdata);
- if ((err != TIFFReadDirEntryErrOk) || (origdata == 0))
- {
- *value = 0;
- return (err);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_SHORT:
- *value = (uint16_t *)origdata;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfShort(*value, count);
- return (TIFFReadDirEntryErrOk);
- case TIFF_SSHORT:
- {
- int16_t *m;
- uint32_t n;
- m = (int16_t *)origdata;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((uint16_t *)m);
- err = TIFFReadDirEntryCheckRangeShortSshort(*m);
- if (err != TIFFReadDirEntryErrOk)
- {
- _TIFFfreeExt(tif, origdata);
- return (err);
- }
- m++;
- }
- *value = (uint16_t *)origdata;
- return (TIFFReadDirEntryErrOk);
- }
- }
- data = (uint16_t *)_TIFFmallocExt(tif, count * 2);
- if (data == 0)
- {
- _TIFFfreeExt(tif, origdata);
- return (TIFFReadDirEntryErrAlloc);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- {
- uint8_t *ma;
- uint16_t *mb;
- uint32_t n;
- ma = (uint8_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- *mb++ = (uint16_t)(*ma++);
- }
- break;
- case TIFF_SBYTE:
- {
- int8_t *ma;
- uint16_t *mb;
- uint32_t n;
- ma = (int8_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- err = TIFFReadDirEntryCheckRangeShortSbyte(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (uint16_t)(*ma++);
- }
- }
- break;
- case TIFF_LONG:
- {
- uint32_t *ma;
- uint16_t *mb;
- uint32_t n;
- ma = (uint32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(ma);
- err = TIFFReadDirEntryCheckRangeShortLong(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (uint16_t)(*ma++);
- }
- }
- break;
- case TIFF_SLONG:
- {
- int32_t *ma;
- uint16_t *mb;
- uint32_t n;
- ma = (int32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong((uint32_t *)ma);
- err = TIFFReadDirEntryCheckRangeShortSlong(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (uint16_t)(*ma++);
- }
- }
- break;
- case TIFF_LONG8:
- {
- uint64_t *ma;
- uint16_t *mb;
- uint32_t n;
- ma = (uint64_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(ma);
- err = TIFFReadDirEntryCheckRangeShortLong8(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (uint16_t)(*ma++);
- }
- }
- break;
- case TIFF_SLONG8:
- {
- int64_t *ma;
- uint16_t *mb;
- uint32_t n;
- ma = (int64_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8((uint64_t *)ma);
- err = TIFFReadDirEntryCheckRangeShortSlong8(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (uint16_t)(*ma++);
- }
- }
- break;
- }
- _TIFFfreeExt(tif, origdata);
- if (err != TIFFReadDirEntryErrOk)
- {
- _TIFFfreeExt(tif, data);
- return (err);
- }
- *value = data;
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntrySshortArray(TIFF *tif, TIFFDirEntry *direntry, int16_t **value)
- {
- enum TIFFReadDirEntryErr err;
- uint32_t count;
- void *origdata;
- int16_t *data;
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- case TIFF_SBYTE:
- case TIFF_SHORT:
- case TIFF_SSHORT:
- case TIFF_LONG:
- case TIFF_SLONG:
- case TIFF_LONG8:
- case TIFF_SLONG8:
- break;
- default:
- return (TIFFReadDirEntryErrType);
- }
- err = TIFFReadDirEntryArray(tif, direntry, &count, 2, &origdata);
- if ((err != TIFFReadDirEntryErrOk) || (origdata == 0))
- {
- *value = 0;
- return (err);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_SHORT:
- {
- uint16_t *m;
- uint32_t n;
- m = (uint16_t *)origdata;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(m);
- err = TIFFReadDirEntryCheckRangeSshortShort(*m);
- if (err != TIFFReadDirEntryErrOk)
- {
- _TIFFfreeExt(tif, origdata);
- return (err);
- }
- m++;
- }
- *value = (int16_t *)origdata;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SSHORT:
- *value = (int16_t *)origdata;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfShort((uint16_t *)(*value), count);
- return (TIFFReadDirEntryErrOk);
- }
- data = (int16_t *)_TIFFmallocExt(tif, count * 2);
- if (data == 0)
- {
- _TIFFfreeExt(tif, origdata);
- return (TIFFReadDirEntryErrAlloc);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- {
- uint8_t *ma;
- int16_t *mb;
- uint32_t n;
- ma = (uint8_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- *mb++ = (int16_t)(*ma++);
- }
- break;
- case TIFF_SBYTE:
- {
- int8_t *ma;
- int16_t *mb;
- uint32_t n;
- ma = (int8_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- *mb++ = (int16_t)(*ma++);
- }
- break;
- case TIFF_LONG:
- {
- uint32_t *ma;
- int16_t *mb;
- uint32_t n;
- ma = (uint32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(ma);
- err = TIFFReadDirEntryCheckRangeSshortLong(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (int16_t)(*ma++);
- }
- }
- break;
- case TIFF_SLONG:
- {
- int32_t *ma;
- int16_t *mb;
- uint32_t n;
- ma = (int32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong((uint32_t *)ma);
- err = TIFFReadDirEntryCheckRangeSshortSlong(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (int16_t)(*ma++);
- }
- }
- break;
- case TIFF_LONG8:
- {
- uint64_t *ma;
- int16_t *mb;
- uint32_t n;
- ma = (uint64_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(ma);
- err = TIFFReadDirEntryCheckRangeSshortLong8(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (int16_t)(*ma++);
- }
- }
- break;
- case TIFF_SLONG8:
- {
- int64_t *ma;
- int16_t *mb;
- uint32_t n;
- ma = (int64_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8((uint64_t *)ma);
- err = TIFFReadDirEntryCheckRangeSshortSlong8(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (int16_t)(*ma++);
- }
- }
- break;
- }
- _TIFFfreeExt(tif, origdata);
- if (err != TIFFReadDirEntryErrOk)
- {
- _TIFFfreeExt(tif, data);
- return (err);
- }
- *value = data;
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryLongArray(TIFF *tif, TIFFDirEntry *direntry, uint32_t **value)
- {
- enum TIFFReadDirEntryErr err;
- uint32_t count;
- void *origdata;
- uint32_t *data;
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- case TIFF_SBYTE:
- case TIFF_SHORT:
- case TIFF_SSHORT:
- case TIFF_LONG:
- case TIFF_SLONG:
- case TIFF_LONG8:
- case TIFF_SLONG8:
- break;
- default:
- return (TIFFReadDirEntryErrType);
- }
- err = TIFFReadDirEntryArray(tif, direntry, &count, 4, &origdata);
- if ((err != TIFFReadDirEntryErrOk) || (origdata == 0))
- {
- *value = 0;
- return (err);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_LONG:
- *value = (uint32_t *)origdata;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong(*value, count);
- return (TIFFReadDirEntryErrOk);
- case TIFF_SLONG:
- {
- int32_t *m;
- uint32_t n;
- m = (int32_t *)origdata;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong((uint32_t *)m);
- err = TIFFReadDirEntryCheckRangeLongSlong(*m);
- if (err != TIFFReadDirEntryErrOk)
- {
- _TIFFfreeExt(tif, origdata);
- return (err);
- }
- m++;
- }
- *value = (uint32_t *)origdata;
- return (TIFFReadDirEntryErrOk);
- }
- }
- data = (uint32_t *)_TIFFmallocExt(tif, count * 4);
- if (data == 0)
- {
- _TIFFfreeExt(tif, origdata);
- return (TIFFReadDirEntryErrAlloc);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- {
- uint8_t *ma;
- uint32_t *mb;
- uint32_t n;
- ma = (uint8_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- *mb++ = (uint32_t)(*ma++);
- }
- break;
- case TIFF_SBYTE:
- {
- int8_t *ma;
- uint32_t *mb;
- uint32_t n;
- ma = (int8_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- err = TIFFReadDirEntryCheckRangeLongSbyte(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (uint32_t)(*ma++);
- }
- }
- break;
- case TIFF_SHORT:
- {
- uint16_t *ma;
- uint32_t *mb;
- uint32_t n;
- ma = (uint16_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(ma);
- *mb++ = (uint32_t)(*ma++);
- }
- }
- break;
- case TIFF_SSHORT:
- {
- int16_t *ma;
- uint32_t *mb;
- uint32_t n;
- ma = (int16_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((uint16_t *)ma);
- err = TIFFReadDirEntryCheckRangeLongSshort(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (uint32_t)(*ma++);
- }
- }
- break;
- case TIFF_LONG8:
- {
- uint64_t *ma;
- uint32_t *mb;
- uint32_t n;
- ma = (uint64_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(ma);
- err = TIFFReadDirEntryCheckRangeLongLong8(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (uint32_t)(*ma++);
- }
- }
- break;
- case TIFF_SLONG8:
- {
- int64_t *ma;
- uint32_t *mb;
- uint32_t n;
- ma = (int64_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8((uint64_t *)ma);
- err = TIFFReadDirEntryCheckRangeLongSlong8(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (uint32_t)(*ma++);
- }
- }
- break;
- }
- _TIFFfreeExt(tif, origdata);
- if (err != TIFFReadDirEntryErrOk)
- {
- _TIFFfreeExt(tif, data);
- return (err);
- }
- *value = data;
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntrySlongArray(TIFF *tif, TIFFDirEntry *direntry, int32_t **value)
- {
- enum TIFFReadDirEntryErr err;
- uint32_t count;
- void *origdata;
- int32_t *data;
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- case TIFF_SBYTE:
- case TIFF_SHORT:
- case TIFF_SSHORT:
- case TIFF_LONG:
- case TIFF_SLONG:
- case TIFF_LONG8:
- case TIFF_SLONG8:
- break;
- default:
- return (TIFFReadDirEntryErrType);
- }
- err = TIFFReadDirEntryArray(tif, direntry, &count, 4, &origdata);
- if ((err != TIFFReadDirEntryErrOk) || (origdata == 0))
- {
- *value = 0;
- return (err);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_LONG:
- {
- uint32_t *m;
- uint32_t n;
- m = (uint32_t *)origdata;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong((uint32_t *)m);
- err = TIFFReadDirEntryCheckRangeSlongLong(*m);
- if (err != TIFFReadDirEntryErrOk)
- {
- _TIFFfreeExt(tif, origdata);
- return (err);
- }
- m++;
- }
- *value = (int32_t *)origdata;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG:
- *value = (int32_t *)origdata;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong((uint32_t *)(*value), count);
- return (TIFFReadDirEntryErrOk);
- }
- data = (int32_t *)_TIFFmallocExt(tif, count * 4);
- if (data == 0)
- {
- _TIFFfreeExt(tif, origdata);
- return (TIFFReadDirEntryErrAlloc);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- {
- uint8_t *ma;
- int32_t *mb;
- uint32_t n;
- ma = (uint8_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- *mb++ = (int32_t)(*ma++);
- }
- break;
- case TIFF_SBYTE:
- {
- int8_t *ma;
- int32_t *mb;
- uint32_t n;
- ma = (int8_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- *mb++ = (int32_t)(*ma++);
- }
- break;
- case TIFF_SHORT:
- {
- uint16_t *ma;
- int32_t *mb;
- uint32_t n;
- ma = (uint16_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(ma);
- *mb++ = (int32_t)(*ma++);
- }
- }
- break;
- case TIFF_SSHORT:
- {
- int16_t *ma;
- int32_t *mb;
- uint32_t n;
- ma = (int16_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((uint16_t *)ma);
- *mb++ = (int32_t)(*ma++);
- }
- }
- break;
- case TIFF_LONG8:
- {
- uint64_t *ma;
- int32_t *mb;
- uint32_t n;
- ma = (uint64_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(ma);
- err = TIFFReadDirEntryCheckRangeSlongLong8(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (int32_t)(*ma++);
- }
- }
- break;
- case TIFF_SLONG8:
- {
- int64_t *ma;
- int32_t *mb;
- uint32_t n;
- ma = (int64_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8((uint64_t *)ma);
- err = TIFFReadDirEntryCheckRangeSlongSlong8(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (int32_t)(*ma++);
- }
- }
- break;
- }
- _TIFFfreeExt(tif, origdata);
- if (err != TIFFReadDirEntryErrOk)
- {
- _TIFFfreeExt(tif, data);
- return (err);
- }
- *value = data;
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryLong8ArrayWithLimit(TIFF *tif, TIFFDirEntry *direntry,
- uint64_t **value, uint64_t maxcount)
- {
- enum TIFFReadDirEntryErr err;
- uint32_t count;
- void *origdata;
- uint64_t *data;
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- case TIFF_SBYTE:
- case TIFF_SHORT:
- case TIFF_SSHORT:
- case TIFF_LONG:
- case TIFF_SLONG:
- case TIFF_LONG8:
- case TIFF_SLONG8:
- break;
- default:
- return (TIFFReadDirEntryErrType);
- }
- err = TIFFReadDirEntryArrayWithLimit(tif, direntry, &count, 8, &origdata,
- maxcount);
- if ((err != TIFFReadDirEntryErrOk) || (origdata == 0))
- {
- *value = 0;
- return (err);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_LONG8:
- *value = (uint64_t *)origdata;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong8(*value, count);
- return (TIFFReadDirEntryErrOk);
- case TIFF_SLONG8:
- {
- int64_t *m;
- uint32_t n;
- m = (int64_t *)origdata;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8((uint64_t *)m);
- err = TIFFReadDirEntryCheckRangeLong8Slong8(*m);
- if (err != TIFFReadDirEntryErrOk)
- {
- _TIFFfreeExt(tif, origdata);
- return (err);
- }
- m++;
- }
- *value = (uint64_t *)origdata;
- return (TIFFReadDirEntryErrOk);
- }
- }
- data = (uint64_t *)_TIFFmallocExt(tif, count * 8);
- if (data == 0)
- {
- _TIFFfreeExt(tif, origdata);
- return (TIFFReadDirEntryErrAlloc);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- {
- uint8_t *ma;
- uint64_t *mb;
- uint32_t n;
- ma = (uint8_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- *mb++ = (uint64_t)(*ma++);
- }
- break;
- case TIFF_SBYTE:
- {
- int8_t *ma;
- uint64_t *mb;
- uint32_t n;
- ma = (int8_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- err = TIFFReadDirEntryCheckRangeLong8Sbyte(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (uint64_t)(*ma++);
- }
- }
- break;
- case TIFF_SHORT:
- {
- uint16_t *ma;
- uint64_t *mb;
- uint32_t n;
- ma = (uint16_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(ma);
- *mb++ = (uint64_t)(*ma++);
- }
- }
- break;
- case TIFF_SSHORT:
- {
- int16_t *ma;
- uint64_t *mb;
- uint32_t n;
- ma = (int16_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((uint16_t *)ma);
- err = TIFFReadDirEntryCheckRangeLong8Sshort(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (uint64_t)(*ma++);
- }
- }
- break;
- case TIFF_LONG:
- {
- uint32_t *ma;
- uint64_t *mb;
- uint32_t n;
- ma = (uint32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(ma);
- *mb++ = (uint64_t)(*ma++);
- }
- }
- break;
- case TIFF_SLONG:
- {
- int32_t *ma;
- uint64_t *mb;
- uint32_t n;
- ma = (int32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong((uint32_t *)ma);
- err = TIFFReadDirEntryCheckRangeLong8Slong(*ma);
- if (err != TIFFReadDirEntryErrOk)
- break;
- *mb++ = (uint64_t)(*ma++);
- }
- }
- break;
- }
- _TIFFfreeExt(tif, origdata);
- if (err != TIFFReadDirEntryErrOk)
- {
- _TIFFfreeExt(tif, data);
- return (err);
- }
- *value = data;
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryLong8Array(TIFF *tif, TIFFDirEntry *direntry, uint64_t **value)
- {
- return TIFFReadDirEntryLong8ArrayWithLimit(tif, direntry, value,
- ~((uint64_t)0));
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntrySlong8Array(TIFF *tif, TIFFDirEntry *direntry, int64_t **value)
- {
- enum TIFFReadDirEntryErr err;
- uint32_t count;
- void *origdata;
- int64_t *data;
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- case TIFF_SBYTE:
- case TIFF_SHORT:
- case TIFF_SSHORT:
- case TIFF_LONG:
- case TIFF_SLONG:
- case TIFF_LONG8:
- case TIFF_SLONG8:
- break;
- default:
- return (TIFFReadDirEntryErrType);
- }
- err = TIFFReadDirEntryArray(tif, direntry, &count, 8, &origdata);
- if ((err != TIFFReadDirEntryErrOk) || (origdata == 0))
- {
- *value = 0;
- return (err);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_LONG8:
- {
- uint64_t *m;
- uint32_t n;
- m = (uint64_t *)origdata;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(m);
- err = TIFFReadDirEntryCheckRangeSlong8Long8(*m);
- if (err != TIFFReadDirEntryErrOk)
- {
- _TIFFfreeExt(tif, origdata);
- return (err);
- }
- m++;
- }
- *value = (int64_t *)origdata;
- return (TIFFReadDirEntryErrOk);
- }
- case TIFF_SLONG8:
- *value = (int64_t *)origdata;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong8((uint64_t *)(*value), count);
- return (TIFFReadDirEntryErrOk);
- }
- data = (int64_t *)_TIFFmallocExt(tif, count * 8);
- if (data == 0)
- {
- _TIFFfreeExt(tif, origdata);
- return (TIFFReadDirEntryErrAlloc);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- {
- uint8_t *ma;
- int64_t *mb;
- uint32_t n;
- ma = (uint8_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- *mb++ = (int64_t)(*ma++);
- }
- break;
- case TIFF_SBYTE:
- {
- int8_t *ma;
- int64_t *mb;
- uint32_t n;
- ma = (int8_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- *mb++ = (int64_t)(*ma++);
- }
- break;
- case TIFF_SHORT:
- {
- uint16_t *ma;
- int64_t *mb;
- uint32_t n;
- ma = (uint16_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(ma);
- *mb++ = (int64_t)(*ma++);
- }
- }
- break;
- case TIFF_SSHORT:
- {
- int16_t *ma;
- int64_t *mb;
- uint32_t n;
- ma = (int16_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((uint16_t *)ma);
- *mb++ = (int64_t)(*ma++);
- }
- }
- break;
- case TIFF_LONG:
- {
- uint32_t *ma;
- int64_t *mb;
- uint32_t n;
- ma = (uint32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(ma);
- *mb++ = (int64_t)(*ma++);
- }
- }
- break;
- case TIFF_SLONG:
- {
- int32_t *ma;
- int64_t *mb;
- uint32_t n;
- ma = (int32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong((uint32_t *)ma);
- *mb++ = (int64_t)(*ma++);
- }
- }
- break;
- }
- _TIFFfreeExt(tif, origdata);
- *value = data;
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryFloatArray(TIFF *tif, TIFFDirEntry *direntry, float **value)
- {
- enum TIFFReadDirEntryErr err;
- uint32_t count;
- void *origdata;
- float *data;
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- case TIFF_SBYTE:
- case TIFF_SHORT:
- case TIFF_SSHORT:
- case TIFF_LONG:
- case TIFF_SLONG:
- case TIFF_LONG8:
- case TIFF_SLONG8:
- case TIFF_RATIONAL:
- case TIFF_SRATIONAL:
- case TIFF_FLOAT:
- case TIFF_DOUBLE:
- break;
- default:
- return (TIFFReadDirEntryErrType);
- }
- err = TIFFReadDirEntryArray(tif, direntry, &count, 4, &origdata);
- if ((err != TIFFReadDirEntryErrOk) || (origdata == 0))
- {
- *value = 0;
- return (err);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_FLOAT:
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong((uint32_t *)origdata, count);
- TIFFCvtIEEEFloatToNative(tif, count, (float *)origdata);
- *value = (float *)origdata;
- return (TIFFReadDirEntryErrOk);
- }
- data = (float *)_TIFFmallocExt(tif, count * sizeof(float));
- if (data == 0)
- {
- _TIFFfreeExt(tif, origdata);
- return (TIFFReadDirEntryErrAlloc);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- {
- uint8_t *ma;
- float *mb;
- uint32_t n;
- ma = (uint8_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- *mb++ = (float)(*ma++);
- }
- break;
- case TIFF_SBYTE:
- {
- int8_t *ma;
- float *mb;
- uint32_t n;
- ma = (int8_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- *mb++ = (float)(*ma++);
- }
- break;
- case TIFF_SHORT:
- {
- uint16_t *ma;
- float *mb;
- uint32_t n;
- ma = (uint16_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(ma);
- *mb++ = (float)(*ma++);
- }
- }
- break;
- case TIFF_SSHORT:
- {
- int16_t *ma;
- float *mb;
- uint32_t n;
- ma = (int16_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((uint16_t *)ma);
- *mb++ = (float)(*ma++);
- }
- }
- break;
- case TIFF_LONG:
- {
- uint32_t *ma;
- float *mb;
- uint32_t n;
- ma = (uint32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(ma);
- *mb++ = (float)(*ma++);
- }
- }
- break;
- case TIFF_SLONG:
- {
- int32_t *ma;
- float *mb;
- uint32_t n;
- ma = (int32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong((uint32_t *)ma);
- *mb++ = (float)(*ma++);
- }
- }
- break;
- case TIFF_LONG8:
- {
- uint64_t *ma;
- float *mb;
- uint32_t n;
- ma = (uint64_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(ma);
- *mb++ = (float)(*ma++);
- }
- }
- break;
- case TIFF_SLONG8:
- {
- int64_t *ma;
- float *mb;
- uint32_t n;
- ma = (int64_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8((uint64_t *)ma);
- *mb++ = (float)(*ma++);
- }
- }
- break;
- case TIFF_RATIONAL:
- {
- uint32_t *ma;
- uint32_t maa;
- uint32_t mab;
- float *mb;
- uint32_t n;
- ma = (uint32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(ma);
- maa = *ma++;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(ma);
- mab = *ma++;
- if (mab == 0)
- *mb++ = 0.0;
- else
- *mb++ = (float)maa / (float)mab;
- }
- }
- break;
- case TIFF_SRATIONAL:
- {
- uint32_t *ma;
- int32_t maa;
- uint32_t mab;
- float *mb;
- uint32_t n;
- ma = (uint32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(ma);
- maa = *(int32_t *)ma;
- ma++;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(ma);
- mab = *ma++;
- if (mab == 0)
- *mb++ = 0.0;
- else
- *mb++ = (float)maa / (float)mab;
- }
- }
- break;
- case TIFF_DOUBLE:
- {
- double *ma;
- float *mb;
- uint32_t n;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong8((uint64_t *)origdata, count);
- TIFFCvtIEEEDoubleToNative(tif, count, (double *)origdata);
- ma = (double *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- double val = *ma++;
- if (val > FLT_MAX)
- val = FLT_MAX;
- else if (val < -FLT_MAX)
- val = -FLT_MAX;
- *mb++ = (float)val;
- }
- }
- break;
- }
- _TIFFfreeExt(tif, origdata);
- *value = data;
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryDoubleArray(TIFF *tif, TIFFDirEntry *direntry, double **value)
- {
- enum TIFFReadDirEntryErr err;
- uint32_t count;
- void *origdata;
- double *data;
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- case TIFF_SBYTE:
- case TIFF_SHORT:
- case TIFF_SSHORT:
- case TIFF_LONG:
- case TIFF_SLONG:
- case TIFF_LONG8:
- case TIFF_SLONG8:
- case TIFF_RATIONAL:
- case TIFF_SRATIONAL:
- case TIFF_FLOAT:
- case TIFF_DOUBLE:
- break;
- default:
- return (TIFFReadDirEntryErrType);
- }
- err = TIFFReadDirEntryArray(tif, direntry, &count, 8, &origdata);
- if ((err != TIFFReadDirEntryErrOk) || (origdata == 0))
- {
- *value = 0;
- return (err);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_DOUBLE:
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong8((uint64_t *)origdata, count);
- TIFFCvtIEEEDoubleToNative(tif, count, (double *)origdata);
- *value = (double *)origdata;
- return (TIFFReadDirEntryErrOk);
- }
- data = (double *)_TIFFmallocExt(tif, count * sizeof(double));
- if (data == 0)
- {
- _TIFFfreeExt(tif, origdata);
- return (TIFFReadDirEntryErrAlloc);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_BYTE:
- {
- uint8_t *ma;
- double *mb;
- uint32_t n;
- ma = (uint8_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- *mb++ = (double)(*ma++);
- }
- break;
- case TIFF_SBYTE:
- {
- int8_t *ma;
- double *mb;
- uint32_t n;
- ma = (int8_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- *mb++ = (double)(*ma++);
- }
- break;
- case TIFF_SHORT:
- {
- uint16_t *ma;
- double *mb;
- uint32_t n;
- ma = (uint16_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(ma);
- *mb++ = (double)(*ma++);
- }
- }
- break;
- case TIFF_SSHORT:
- {
- int16_t *ma;
- double *mb;
- uint32_t n;
- ma = (int16_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((uint16_t *)ma);
- *mb++ = (double)(*ma++);
- }
- }
- break;
- case TIFF_LONG:
- {
- uint32_t *ma;
- double *mb;
- uint32_t n;
- ma = (uint32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(ma);
- *mb++ = (double)(*ma++);
- }
- }
- break;
- case TIFF_SLONG:
- {
- int32_t *ma;
- double *mb;
- uint32_t n;
- ma = (int32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong((uint32_t *)ma);
- *mb++ = (double)(*ma++);
- }
- }
- break;
- case TIFF_LONG8:
- {
- uint64_t *ma;
- double *mb;
- uint32_t n;
- ma = (uint64_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(ma);
- *mb++ = (double)(*ma++);
- }
- }
- break;
- case TIFF_SLONG8:
- {
- int64_t *ma;
- double *mb;
- uint32_t n;
- ma = (int64_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8((uint64_t *)ma);
- *mb++ = (double)(*ma++);
- }
- }
- break;
- case TIFF_RATIONAL:
- {
- uint32_t *ma;
- uint32_t maa;
- uint32_t mab;
- double *mb;
- uint32_t n;
- ma = (uint32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(ma);
- maa = *ma++;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(ma);
- mab = *ma++;
- if (mab == 0)
- *mb++ = 0.0;
- else
- *mb++ = (double)maa / (double)mab;
- }
- }
- break;
- case TIFF_SRATIONAL:
- {
- uint32_t *ma;
- int32_t maa;
- uint32_t mab;
- double *mb;
- uint32_t n;
- ma = (uint32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(ma);
- maa = *(int32_t *)ma;
- ma++;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(ma);
- mab = *ma++;
- if (mab == 0)
- *mb++ = 0.0;
- else
- *mb++ = (double)maa / (double)mab;
- }
- }
- break;
- case TIFF_FLOAT:
- {
- float *ma;
- double *mb;
- uint32_t n;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong((uint32_t *)origdata, count);
- TIFFCvtIEEEFloatToNative(tif, count, (float *)origdata);
- ma = (float *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- *mb++ = (double)(*ma++);
- }
- break;
- }
- _TIFFfreeExt(tif, origdata);
- *value = data;
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryIfd8Array(TIFF *tif, TIFFDirEntry *direntry, uint64_t **value)
- {
- enum TIFFReadDirEntryErr err;
- uint32_t count;
- void *origdata;
- uint64_t *data;
- switch (direntry->tdir_type)
- {
- case TIFF_LONG:
- case TIFF_LONG8:
- case TIFF_IFD:
- case TIFF_IFD8:
- break;
- default:
- return (TIFFReadDirEntryErrType);
- }
- err = TIFFReadDirEntryArray(tif, direntry, &count, 8, &origdata);
- if ((err != TIFFReadDirEntryErrOk) || (origdata == 0))
- {
- *value = 0;
- return (err);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_LONG8:
- case TIFF_IFD8:
- *value = (uint64_t *)origdata;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong8(*value, count);
- return (TIFFReadDirEntryErrOk);
- }
- data = (uint64_t *)_TIFFmallocExt(tif, count * 8);
- if (data == 0)
- {
- _TIFFfreeExt(tif, origdata);
- return (TIFFReadDirEntryErrAlloc);
- }
- switch (direntry->tdir_type)
- {
- case TIFF_LONG:
- case TIFF_IFD:
- {
- uint32_t *ma;
- uint64_t *mb;
- uint32_t n;
- ma = (uint32_t *)origdata;
- mb = data;
- for (n = 0; n < count; n++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(ma);
- *mb++ = (uint64_t)(*ma++);
- }
- }
- break;
- }
- _TIFFfreeExt(tif, origdata);
- *value = data;
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryPersampleShort(TIFF *tif, TIFFDirEntry *direntry,
- uint16_t *value)
- {
- enum TIFFReadDirEntryErr err;
- uint16_t *m;
- uint16_t *na;
- uint16_t nb;
- if (direntry->tdir_count < (uint64_t)tif->tif_dir.td_samplesperpixel)
- return (TIFFReadDirEntryErrCount);
- err = TIFFReadDirEntryShortArray(tif, direntry, &m);
- if (err != TIFFReadDirEntryErrOk || m == NULL)
- return (err);
- na = m;
- nb = tif->tif_dir.td_samplesperpixel;
- *value = *na++;
- nb--;
- while (nb > 0)
- {
- if (*na++ != *value)
- {
- err = TIFFReadDirEntryErrPsdif;
- break;
- }
- nb--;
- }
- _TIFFfreeExt(tif, m);
- return (err);
- }
- static void TIFFReadDirEntryCheckedByte(TIFF *tif, TIFFDirEntry *direntry,
- uint8_t *value)
- {
- (void)tif;
- *value = *(uint8_t *)(&direntry->tdir_offset);
- }
- static void TIFFReadDirEntryCheckedSbyte(TIFF *tif, TIFFDirEntry *direntry,
- int8_t *value)
- {
- (void)tif;
- *value = *(int8_t *)(&direntry->tdir_offset);
- }
- static void TIFFReadDirEntryCheckedShort(TIFF *tif, TIFFDirEntry *direntry,
- uint16_t *value)
- {
- *value = direntry->tdir_offset.toff_short;
- /* *value=*(uint16_t*)(&direntry->tdir_offset); */
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(value);
- }
- static void TIFFReadDirEntryCheckedSshort(TIFF *tif, TIFFDirEntry *direntry,
- int16_t *value)
- {
- *value = *(int16_t *)(&direntry->tdir_offset);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((uint16_t *)value);
- }
- static void TIFFReadDirEntryCheckedLong(TIFF *tif, TIFFDirEntry *direntry,
- uint32_t *value)
- {
- *value = *(uint32_t *)(&direntry->tdir_offset);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(value);
- }
- static void TIFFReadDirEntryCheckedSlong(TIFF *tif, TIFFDirEntry *direntry,
- int32_t *value)
- {
- *value = *(int32_t *)(&direntry->tdir_offset);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong((uint32_t *)value);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckedLong8(TIFF *tif, TIFFDirEntry *direntry, uint64_t *value)
- {
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- enum TIFFReadDirEntryErr err;
- uint32_t offset = direntry->tdir_offset.toff_long;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&offset);
- err = TIFFReadDirEntryData(tif, offset, 8, value);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- }
- else
- *value = direntry->tdir_offset.toff_long8;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(value);
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckedSlong8(TIFF *tif, TIFFDirEntry *direntry, int64_t *value)
- {
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- enum TIFFReadDirEntryErr err;
- uint32_t offset = direntry->tdir_offset.toff_long;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&offset);
- err = TIFFReadDirEntryData(tif, offset, 8, value);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- }
- else
- *value = *(int64_t *)(&direntry->tdir_offset);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8((uint64_t *)value);
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckedRational(TIFF *tif, TIFFDirEntry *direntry,
- double *value)
- {
- UInt64Aligned_t m;
- assert(sizeof(double) == 8);
- assert(sizeof(uint64_t) == 8);
- assert(sizeof(uint32_t) == 4);
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- enum TIFFReadDirEntryErr err;
- uint32_t offset = direntry->tdir_offset.toff_long;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&offset);
- err = TIFFReadDirEntryData(tif, offset, 8, m.i);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- }
- else
- m.l = direntry->tdir_offset.toff_long8;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong(m.i, 2);
- /* Not completely sure what we should do when m.i[1]==0, but some */
- /* sanitizers do not like division by 0.0: */
- /* http://bugzilla.maptools.org/show_bug.cgi?id=2644 */
- if (m.i[0] == 0 || m.i[1] == 0)
- *value = 0.0;
- else
- *value = (double)m.i[0] / (double)m.i[1];
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckedSrational(TIFF *tif, TIFFDirEntry *direntry,
- double *value)
- {
- UInt64Aligned_t m;
- assert(sizeof(double) == 8);
- assert(sizeof(uint64_t) == 8);
- assert(sizeof(int32_t) == 4);
- assert(sizeof(uint32_t) == 4);
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- enum TIFFReadDirEntryErr err;
- uint32_t offset = direntry->tdir_offset.toff_long;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&offset);
- err = TIFFReadDirEntryData(tif, offset, 8, m.i);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- }
- else
- m.l = direntry->tdir_offset.toff_long8;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong(m.i, 2);
- /* Not completely sure what we should do when m.i[1]==0, but some */
- /* sanitizers do not like division by 0.0: */
- /* http://bugzilla.maptools.org/show_bug.cgi?id=2644 */
- if ((int32_t)m.i[0] == 0 || m.i[1] == 0)
- *value = 0.0;
- else
- *value = (double)((int32_t)m.i[0]) / (double)m.i[1];
- return (TIFFReadDirEntryErrOk);
- }
- #if 0
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckedRationalDirect(TIFF *tif, TIFFDirEntry *direntry,
- TIFFRational_t *value)
- { /*--: SetGetRATIONAL_directly:_CustomTag: Read rational (and signed rationals)
- directly --*/
- UInt64Aligned_t m;
- assert(sizeof(double) == 8);
- assert(sizeof(uint64_t) == 8);
- assert(sizeof(uint32_t) == 4);
- if (direntry->tdir_count != 1)
- return (TIFFReadDirEntryErrCount);
- if (direntry->tdir_type != TIFF_RATIONAL &&
- direntry->tdir_type != TIFF_SRATIONAL)
- return (TIFFReadDirEntryErrType);
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- enum TIFFReadDirEntryErr err;
- uint32_t offset = direntry->tdir_offset.toff_long;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&offset);
- err = TIFFReadDirEntryData(tif, offset, 8, m.i);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- }
- else
- {
- m.l = direntry->tdir_offset.toff_long8;
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong(m.i, 2);
- value->uNum = m.i[0];
- value->uDenom = m.i[1];
- return (TIFFReadDirEntryErrOk);
- } /*-- TIFFReadDirEntryCheckedRationalDirect() --*/
- #endif
- static void TIFFReadDirEntryCheckedFloat(TIFF *tif, TIFFDirEntry *direntry,
- float *value)
- {
- union
- {
- float f;
- uint32_t i;
- } float_union;
- assert(sizeof(float) == 4);
- assert(sizeof(uint32_t) == 4);
- assert(sizeof(float_union) == 4);
- float_union.i = *(uint32_t *)(&direntry->tdir_offset);
- *value = float_union.f;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong((uint32_t *)value);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckedDouble(TIFF *tif, TIFFDirEntry *direntry, double *value)
- {
- assert(sizeof(double) == 8);
- assert(sizeof(uint64_t) == 8);
- assert(sizeof(UInt64Aligned_t) == 8);
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- enum TIFFReadDirEntryErr err;
- uint32_t offset = direntry->tdir_offset.toff_long;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&offset);
- err = TIFFReadDirEntryData(tif, offset, 8, value);
- if (err != TIFFReadDirEntryErrOk)
- return (err);
- }
- else
- {
- UInt64Aligned_t uint64_union;
- uint64_union.l = direntry->tdir_offset.toff_long8;
- *value = uint64_union.d;
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8((uint64_t *)value);
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeByteSbyte(int8_t value)
- {
- if (value < 0)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeByteShort(uint16_t value)
- {
- if (value > 0xFF)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeByteSshort(int16_t value)
- {
- if ((value < 0) || (value > 0xFF))
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeByteLong(uint32_t value)
- {
- if (value > 0xFF)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeByteSlong(int32_t value)
- {
- if ((value < 0) || (value > 0xFF))
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeByteLong8(uint64_t value)
- {
- if (value > 0xFF)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeByteSlong8(int64_t value)
- {
- if ((value < 0) || (value > 0xFF))
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSbyteByte(uint8_t value)
- {
- if (value > 0x7F)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSbyteShort(uint16_t value)
- {
- if (value > 0x7F)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSbyteSshort(int16_t value)
- {
- if ((value < -0x80) || (value > 0x7F))
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSbyteLong(uint32_t value)
- {
- if (value > 0x7F)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSbyteSlong(int32_t value)
- {
- if ((value < -0x80) || (value > 0x7F))
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSbyteLong8(uint64_t value)
- {
- if (value > 0x7F)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSbyteSlong8(int64_t value)
- {
- if ((value < -0x80) || (value > 0x7F))
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeShortSbyte(int8_t value)
- {
- if (value < 0)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeShortSshort(int16_t value)
- {
- if (value < 0)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeShortLong(uint32_t value)
- {
- if (value > 0xFFFF)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeShortSlong(int32_t value)
- {
- if ((value < 0) || (value > 0xFFFF))
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeShortLong8(uint64_t value)
- {
- if (value > 0xFFFF)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeShortSlong8(int64_t value)
- {
- if ((value < 0) || (value > 0xFFFF))
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSshortShort(uint16_t value)
- {
- if (value > 0x7FFF)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSshortLong(uint32_t value)
- {
- if (value > 0x7FFF)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSshortSlong(int32_t value)
- {
- if ((value < -0x8000) || (value > 0x7FFF))
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSshortLong8(uint64_t value)
- {
- if (value > 0x7FFF)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSshortSlong8(int64_t value)
- {
- if ((value < -0x8000) || (value > 0x7FFF))
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeLongSbyte(int8_t value)
- {
- if (value < 0)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeLongSshort(int16_t value)
- {
- if (value < 0)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeLongSlong(int32_t value)
- {
- if (value < 0)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeLongLong8(uint64_t value)
- {
- if (value > UINT32_MAX)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeLongSlong8(int64_t value)
- {
- if ((value < 0) || (value > (int64_t)UINT32_MAX))
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSlongLong(uint32_t value)
- {
- if (value > 0x7FFFFFFFUL)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- /* Check that the 8-byte unsigned value can fit in a 4-byte unsigned range */
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSlongLong8(uint64_t value)
- {
- if (value > 0x7FFFFFFF)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- /* Check that the 8-byte signed value can fit in a 4-byte signed range */
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSlongSlong8(int64_t value)
- {
- if ((value < 0 - ((int64_t)0x7FFFFFFF + 1)) || (value > 0x7FFFFFFF))
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeLong8Sbyte(int8_t value)
- {
- if (value < 0)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeLong8Sshort(int16_t value)
- {
- if (value < 0)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeLong8Slong(int32_t value)
- {
- if (value < 0)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeLong8Slong8(int64_t value)
- {
- if (value < 0)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr
- TIFFReadDirEntryCheckRangeSlong8Long8(uint64_t value)
- {
- if (value > INT64_MAX)
- return (TIFFReadDirEntryErrRange);
- else
- return (TIFFReadDirEntryErrOk);
- }
- static enum TIFFReadDirEntryErr TIFFReadDirEntryData(TIFF *tif, uint64_t offset,
- tmsize_t size, void *dest)
- {
- assert(size > 0);
- if (!isMapped(tif))
- {
- if (!SeekOK(tif, offset))
- return (TIFFReadDirEntryErrIo);
- if (!ReadOK(tif, dest, size))
- return (TIFFReadDirEntryErrIo);
- }
- else
- {
- size_t ma, mb;
- ma = (size_t)offset;
- if ((uint64_t)ma != offset || ma > (~(size_t)0) - (size_t)size)
- {
- return TIFFReadDirEntryErrIo;
- }
- mb = ma + size;
- if (mb > (uint64_t)tif->tif_size)
- return (TIFFReadDirEntryErrIo);
- _TIFFmemcpy(dest, tif->tif_base + ma, size);
- }
- return (TIFFReadDirEntryErrOk);
- }
- static void TIFFReadDirEntryOutputErr(TIFF *tif, enum TIFFReadDirEntryErr err,
- const char *module, const char *tagname,
- int recover)
- {
- if (!recover)
- {
- switch (err)
- {
- case TIFFReadDirEntryErrCount:
- TIFFErrorExtR(tif, module, "Incorrect count for \"%s\"",
- tagname);
- break;
- case TIFFReadDirEntryErrType:
- TIFFErrorExtR(tif, module, "Incompatible type for \"%s\"",
- tagname);
- break;
- case TIFFReadDirEntryErrIo:
- TIFFErrorExtR(tif, module, "IO error during reading of \"%s\"",
- tagname);
- break;
- case TIFFReadDirEntryErrRange:
- TIFFErrorExtR(tif, module, "Incorrect value for \"%s\"",
- tagname);
- break;
- case TIFFReadDirEntryErrPsdif:
- TIFFErrorExtR(
- tif, module,
- "Cannot handle different values per sample for \"%s\"",
- tagname);
- break;
- case TIFFReadDirEntryErrSizesan:
- TIFFErrorExtR(tif, module,
- "Sanity check on size of \"%s\" value failed",
- tagname);
- break;
- case TIFFReadDirEntryErrAlloc:
- TIFFErrorExtR(tif, module, "Out of memory reading of \"%s\"",
- tagname);
- break;
- default:
- assert(0); /* we should never get here */
- break;
- }
- }
- else
- {
- switch (err)
- {
- case TIFFReadDirEntryErrCount:
- TIFFWarningExtR(tif, module,
- "Incorrect count for \"%s\"; tag ignored",
- tagname);
- break;
- case TIFFReadDirEntryErrType:
- TIFFWarningExtR(tif, module,
- "Incompatible type for \"%s\"; tag ignored",
- tagname);
- break;
- case TIFFReadDirEntryErrIo:
- TIFFWarningExtR(
- tif, module,
- "IO error during reading of \"%s\"; tag ignored", tagname);
- break;
- case TIFFReadDirEntryErrRange:
- TIFFWarningExtR(tif, module,
- "Incorrect value for \"%s\"; tag ignored",
- tagname);
- break;
- case TIFFReadDirEntryErrPsdif:
- TIFFWarningExtR(tif, module,
- "Cannot handle different values per sample for "
- "\"%s\"; tag ignored",
- tagname);
- break;
- case TIFFReadDirEntryErrSizesan:
- TIFFWarningExtR(
- tif, module,
- "Sanity check on size of \"%s\" value failed; tag ignored",
- tagname);
- break;
- case TIFFReadDirEntryErrAlloc:
- TIFFWarningExtR(tif, module,
- "Out of memory reading of \"%s\"; tag ignored",
- tagname);
- break;
- default:
- assert(0); /* we should never get here */
- break;
- }
- }
- }
- /*
- * Return the maximum number of color channels specified for a given photometric
- * type. 0 is returned if photometric type isn't supported or no default value
- * is defined by the specification.
- */
- static int _TIFFGetMaxColorChannels(uint16_t photometric)
- {
- switch (photometric)
- {
- case PHOTOMETRIC_PALETTE:
- case PHOTOMETRIC_MINISWHITE:
- case PHOTOMETRIC_MINISBLACK:
- return 1;
- case PHOTOMETRIC_YCBCR:
- case PHOTOMETRIC_RGB:
- case PHOTOMETRIC_CIELAB:
- case PHOTOMETRIC_LOGLUV:
- case PHOTOMETRIC_ITULAB:
- case PHOTOMETRIC_ICCLAB:
- return 3;
- case PHOTOMETRIC_SEPARATED:
- case PHOTOMETRIC_MASK:
- return 4;
- case PHOTOMETRIC_LOGL:
- case PHOTOMETRIC_CFA:
- default:
- return 0;
- }
- }
- static int ByteCountLooksBad(TIFF *tif)
- {
- /*
- * Assume we have wrong StripByteCount value (in case
- * of single strip) in following cases:
- * - it is equal to zero along with StripOffset;
- * - it is larger than file itself (in case of uncompressed
- * image);
- * - it is smaller than the size of the bytes per row
- * multiplied on the number of rows. The last case should
- * not be checked in the case of writing new image,
- * because we may do not know the exact strip size
- * until the whole image will be written and directory
- * dumped out.
- */
- uint64_t bytecount = TIFFGetStrileByteCount(tif, 0);
- uint64_t offset = TIFFGetStrileOffset(tif, 0);
- uint64_t filesize;
- if (offset == 0)
- return 0;
- if (bytecount == 0)
- return 1;
- if (tif->tif_dir.td_compression != COMPRESSION_NONE)
- return 0;
- filesize = TIFFGetFileSize(tif);
- if (offset <= filesize && bytecount > filesize - offset)
- return 1;
- if (tif->tif_mode == O_RDONLY)
- {
- uint64_t scanlinesize = TIFFScanlineSize64(tif);
- if (tif->tif_dir.td_imagelength > 0 &&
- scanlinesize > UINT64_MAX / tif->tif_dir.td_imagelength)
- {
- return 1;
- }
- if (bytecount < scanlinesize * tif->tif_dir.td_imagelength)
- return 1;
- }
- return 0;
- }
- /*
- * To evaluate the IFD data size when reading, save the offset and data size of
- * all data that does not fit into the IFD entries themselves.
- */
- static bool EvaluateIFDdatasizeReading(TIFF *tif, TIFFDirEntry *dp)
- {
- const uint64_t data_width = TIFFDataWidth(dp->tdir_type);
- if (data_width != 0 && dp->tdir_count > UINT64_MAX / data_width)
- {
- TIFFErrorExtR(tif, "EvaluateIFDdatasizeReading",
- "Too large IFD data size");
- return false;
- }
- const uint64_t datalength = dp->tdir_count * data_width;
- if (datalength > ((tif->tif_flags & TIFF_BIGTIFF) ? 0x8U : 0x4U))
- {
- if (tif->tif_dir.td_dirdatasize_read > UINT64_MAX - datalength)
- {
- TIFFErrorExtR(tif, "EvaluateIFDdatasizeReading",
- "Too large IFD data size");
- return false;
- }
- tif->tif_dir.td_dirdatasize_read += datalength;
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- /* The offset of TIFFDirEntry are not swapped when read in. That has
- * to be done when used. */
- uint32_t offset = dp->tdir_offset.toff_long;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&offset);
- tif->tif_dir
- .td_dirdatasize_offsets[tif->tif_dir.td_dirdatasize_Noffsets]
- .offset = (uint64_t)offset;
- }
- else
- {
- tif->tif_dir
- .td_dirdatasize_offsets[tif->tif_dir.td_dirdatasize_Noffsets]
- .offset = dp->tdir_offset.toff_long8;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(
- &tif->tif_dir
- .td_dirdatasize_offsets[tif->tif_dir
- .td_dirdatasize_Noffsets]
- .offset);
- }
- tif->tif_dir
- .td_dirdatasize_offsets[tif->tif_dir.td_dirdatasize_Noffsets]
- .length = datalength;
- tif->tif_dir.td_dirdatasize_Noffsets++;
- }
- return true;
- }
- /*
- * Compare function for qsort() sorting TIFFEntryOffsetAndLength array entries.
- */
- static int cmpTIFFEntryOffsetAndLength(const void *a, const void *b)
- {
- const TIFFEntryOffsetAndLength *ta = (const TIFFEntryOffsetAndLength *)a;
- const TIFFEntryOffsetAndLength *tb = (const TIFFEntryOffsetAndLength *)b;
- /* Compare offsets */
- if (ta->offset > tb->offset)
- return 1;
- else if (ta->offset < tb->offset)
- return -1;
- else
- return 0;
- }
- /*
- * Determine the IFD data size after reading an IFD from the file that can be
- * overwritten and saving it in tif_dir.td_dirdatasize_read. This data size
- * includes the IFD entries themselves as well as the data that does not fit
- * directly into the IFD entries but is located directly after the IFD entries
- * in the file.
- */
- static void CalcFinalIFDdatasizeReading(TIFF *tif, uint16_t dircount)
- {
- /* IFD data size is only needed if file-writing is enabled.
- * This also avoids the seek() to EOF to determine the file size, which
- * causes the stdin-streaming-friendly mode of libtiff for GDAL to fail. */
- if (tif->tif_mode == O_RDONLY)
- return;
- /* Sort TIFFEntryOffsetAndLength array in ascending order. */
- qsort(tif->tif_dir.td_dirdatasize_offsets,
- tif->tif_dir.td_dirdatasize_Noffsets,
- sizeof(TIFFEntryOffsetAndLength), cmpTIFFEntryOffsetAndLength);
- /* Get offset of end of IFD entry space. */
- uint64_t IFDendoffset;
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- IFDendoffset = tif->tif_diroff + 2 + dircount * 12 + 4;
- else
- IFDendoffset = tif->tif_diroff + 8 + dircount * 20 + 8;
- /* Check which offsets are right behind IFD entries. However, LibTIFF
- * increments the writing address for every external data to an even offset.
- * Thus gaps of 1 byte can occur. */
- uint64_t size = 0;
- uint64_t offset;
- uint32_t i;
- for (i = 0; i < tif->tif_dir.td_dirdatasize_Noffsets; i++)
- {
- offset = tif->tif_dir.td_dirdatasize_offsets[i].offset;
- if (offset == IFDendoffset)
- {
- size += tif->tif_dir.td_dirdatasize_offsets[i].length;
- IFDendoffset += tif->tif_dir.td_dirdatasize_offsets[i].length;
- }
- else if (offset == IFDendoffset + 1)
- {
- /* Add gap byte after previous IFD data set. */
- size += tif->tif_dir.td_dirdatasize_offsets[i].length + 1;
- IFDendoffset += tif->tif_dir.td_dirdatasize_offsets[i].length;
- }
- else
- {
- /* Further data is no more continuously after IFD */
- break;
- }
- }
- /* Check for gap byte of some easy cases. This should cover 90% of cases.
- * Otherwise, IFD will be re-written even it might be safely overwritten. */
- if (tif->tif_nextdiroff != 0)
- {
- if (tif->tif_nextdiroff == IFDendoffset + 1)
- size++;
- }
- else
- {
- /* Check for IFD data ends at EOF. Then IFD can always be safely
- * overwritten. */
- offset = TIFFSeekFile(tif, 0, SEEK_END);
- if (offset == IFDendoffset)
- {
- tif->tif_dir.td_dirdatasize_read = UINT64_MAX;
- return;
- }
- }
- /* Finally, add the size of the IFD tag entries themselves. */
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- tif->tif_dir.td_dirdatasize_read = 2 + dircount * 12 + 4 + size;
- else
- tif->tif_dir.td_dirdatasize_read = 8 + dircount * 20 + 8 + size;
- } /*-- CalcFinalIFDdatasizeReading() --*/
- /*
- * Read the next TIFF directory from a file and convert it to the internal
- * format. We read directories sequentially.
- */
- int TIFFReadDirectory(TIFF *tif)
- {
- static const char module[] = "TIFFReadDirectory";
- TIFFDirEntry *dir;
- uint16_t dircount;
- TIFFDirEntry *dp;
- uint16_t di;
- const TIFFField *fip;
- uint32_t fii = FAILED_FII;
- toff_t nextdiroff;
- int bitspersample_read = FALSE;
- int color_channels;
- if (tif->tif_nextdiroff == 0)
- {
- /* In this special case, tif_diroff needs also to be set to 0.
- * This is behind the last IFD, thus no checking or reading necessary.
- */
- tif->tif_diroff = tif->tif_nextdiroff;
- return 0;
- }
- nextdiroff = tif->tif_nextdiroff;
- /* tif_curdir++ and tif_nextdiroff should only be updated after SUCCESSFUL
- * reading of the directory. Otherwise, invalid IFD offsets could corrupt
- * the IFD list. */
- if (!_TIFFCheckDirNumberAndOffset(tif,
- tif->tif_curdir ==
- TIFF_NON_EXISTENT_DIR_NUMBER
- ? 0
- : tif->tif_curdir + 1,
- nextdiroff))
- {
- return 0; /* bad offset (IFD looping or more than TIFF_MAX_DIR_COUNT
- IFDs) */
- }
- dircount = TIFFFetchDirectory(tif, nextdiroff, &dir, &tif->tif_nextdiroff);
- if (!dircount)
- {
- TIFFErrorExtR(tif, module,
- "Failed to read directory at offset %" PRIu64,
- nextdiroff);
- return 0;
- }
- /* Set global values after a valid directory has been fetched.
- * tif_diroff is already set to nextdiroff in TIFFFetchDirectory() in the
- * beginning. */
- if (tif->tif_curdir == TIFF_NON_EXISTENT_DIR_NUMBER)
- tif->tif_curdir = 0;
- else
- tif->tif_curdir++;
- TIFFReadDirectoryCheckOrder(tif, dir, dircount);
- /*
- * Mark duplicates of any tag to be ignored (bugzilla 1994)
- * to avoid certain pathological problems.
- */
- {
- TIFFDirEntry *ma;
- uint16_t mb;
- for (ma = dir, mb = 0; mb < dircount; ma++, mb++)
- {
- TIFFDirEntry *na;
- uint16_t nb;
- for (na = ma + 1, nb = mb + 1; nb < dircount; na++, nb++)
- {
- if (ma->tdir_tag == na->tdir_tag)
- {
- na->tdir_ignore = TRUE;
- }
- }
- }
- }
- tif->tif_flags &= ~TIFF_BEENWRITING; /* reset before new dir */
- tif->tif_flags &= ~TIFF_BUF4WRITE; /* reset before new dir */
- tif->tif_flags &= ~TIFF_CHOPPEDUPARRAYS;
- /* free any old stuff and reinit */
- TIFFFreeDirectory(tif);
- TIFFDefaultDirectory(tif);
- /* After setup a fresh directory indicate that now active IFD is also
- * present on file, even if its entries could not be read successfully
- * below. */
- tif->tif_dir.td_iswrittentofile = TRUE;
- /* Allocate arrays for offset values outside IFD entry for IFD data size
- * checking. Note: Counter are reset within TIFFFreeDirectory(). */
- tif->tif_dir.td_dirdatasize_offsets =
- (TIFFEntryOffsetAndLength *)_TIFFmallocExt(
- tif, dircount * sizeof(TIFFEntryOffsetAndLength));
- if (tif->tif_dir.td_dirdatasize_offsets == NULL)
- {
- TIFFErrorExtR(
- tif, module,
- "Failed to allocate memory for counting IFD data size at reading");
- goto bad;
- }
- /*
- * Electronic Arts writes gray-scale TIFF files
- * without a PlanarConfiguration directory entry.
- * Thus we setup a default value here, even though
- * the TIFF spec says there is no default value.
- * After PlanarConfiguration is preset in TIFFDefaultDirectory()
- * the following setting is not needed, but does not harm either.
- */
- TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
- /*
- * Setup default value and then make a pass over
- * the fields to check type and tag information,
- * and to extract info required to size data
- * structures. A second pass is made afterwards
- * to read in everything not taken in the first pass.
- * But we must process the Compression tag first
- * in order to merge in codec-private tag definitions (otherwise
- * we may get complaints about unknown tags). However, the
- * Compression tag may be dependent on the SamplesPerPixel
- * tag value because older TIFF specs permitted Compression
- * to be written as a SamplesPerPixel-count tag entry.
- * Thus if we don't first figure out the correct SamplesPerPixel
- * tag value then we may end up ignoring the Compression tag
- * value because it has an incorrect count value (if the
- * true value of SamplesPerPixel is not 1).
- */
- dp =
- TIFFReadDirectoryFindEntry(tif, dir, dircount, TIFFTAG_SAMPLESPERPIXEL);
- if (dp)
- {
- if (!TIFFFetchNormalTag(tif, dp, 0))
- goto bad;
- dp->tdir_ignore = TRUE;
- }
- dp = TIFFReadDirectoryFindEntry(tif, dir, dircount, TIFFTAG_COMPRESSION);
- if (dp)
- {
- /*
- * The 5.0 spec says the Compression tag has one value, while
- * earlier specs say it has one value per sample. Because of
- * this, we accept the tag if one value is supplied with either
- * count.
- */
- uint16_t value;
- enum TIFFReadDirEntryErr err;
- err = TIFFReadDirEntryShort(tif, dp, &value);
- if (err == TIFFReadDirEntryErrCount)
- err = TIFFReadDirEntryPersampleShort(tif, dp, &value);
- if (err != TIFFReadDirEntryErrOk)
- {
- TIFFReadDirEntryOutputErr(tif, err, module, "Compression", 0);
- goto bad;
- }
- if (!TIFFSetField(tif, TIFFTAG_COMPRESSION, value))
- goto bad;
- dp->tdir_ignore = TRUE;
- }
- else
- {
- if (!TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE))
- goto bad;
- }
- /*
- * First real pass over the directory.
- */
- for (di = 0, dp = dir; di < dircount; di++, dp++)
- {
- if (!dp->tdir_ignore)
- {
- TIFFReadDirectoryFindFieldInfo(tif, dp->tdir_tag, &fii);
- if (fii == FAILED_FII)
- {
- if (tif->tif_warn_about_unknown_tags)
- {
- TIFFWarningExtR(tif, module,
- "Unknown field with tag %" PRIu16
- " (0x%" PRIx16 ") encountered",
- dp->tdir_tag, dp->tdir_tag);
- }
- /* the following knowingly leaks the
- anonymous field structure */
- const TIFFField *fld = _TIFFCreateAnonField(
- tif, dp->tdir_tag, (TIFFDataType)dp->tdir_type);
- if (fld == NULL || !_TIFFMergeFields(tif, fld, 1))
- {
- TIFFWarningExtR(
- tif, module,
- "Registering anonymous field with tag %" PRIu16
- " (0x%" PRIx16 ") failed",
- dp->tdir_tag, dp->tdir_tag);
- dp->tdir_ignore = TRUE;
- }
- else
- {
- TIFFReadDirectoryFindFieldInfo(tif, dp->tdir_tag, &fii);
- assert(fii != FAILED_FII);
- }
- }
- }
- if (!dp->tdir_ignore)
- {
- fip = tif->tif_fields[fii];
- if (fip->field_bit == FIELD_IGNORE)
- dp->tdir_ignore = TRUE;
- else
- {
- switch (dp->tdir_tag)
- {
- case TIFFTAG_STRIPOFFSETS:
- case TIFFTAG_STRIPBYTECOUNTS:
- case TIFFTAG_TILEOFFSETS:
- case TIFFTAG_TILEBYTECOUNTS:
- TIFFSetFieldBit(tif, fip->field_bit);
- break;
- case TIFFTAG_IMAGEWIDTH:
- case TIFFTAG_IMAGELENGTH:
- case TIFFTAG_IMAGEDEPTH:
- case TIFFTAG_TILELENGTH:
- case TIFFTAG_TILEWIDTH:
- case TIFFTAG_TILEDEPTH:
- case TIFFTAG_PLANARCONFIG:
- case TIFFTAG_ROWSPERSTRIP:
- case TIFFTAG_EXTRASAMPLES:
- if (!TIFFFetchNormalTag(tif, dp, 0))
- goto bad;
- dp->tdir_ignore = TRUE;
- break;
- default:
- if (!_TIFFCheckFieldIsValidForCodec(tif, dp->tdir_tag))
- dp->tdir_ignore = TRUE;
- break;
- }
- }
- }
- }
- /*
- * XXX: OJPEG hack.
- * If a) compression is OJPEG, b) planarconfig tag says it's separate,
- * c) strip offsets/bytecounts tag are both present and
- * d) both contain exactly one value, then we consistently find
- * that the buggy implementation of the buggy compression scheme
- * matches contig planarconfig best. So we 'fix-up' the tag here
- */
- if ((tif->tif_dir.td_compression == COMPRESSION_OJPEG) &&
- (tif->tif_dir.td_planarconfig == PLANARCONFIG_SEPARATE))
- {
- if (!_TIFFFillStriles(tif))
- goto bad;
- dp = TIFFReadDirectoryFindEntry(tif, dir, dircount,
- TIFFTAG_STRIPOFFSETS);
- if ((dp != 0) && (dp->tdir_count == 1))
- {
- dp = TIFFReadDirectoryFindEntry(tif, dir, dircount,
- TIFFTAG_STRIPBYTECOUNTS);
- if ((dp != 0) && (dp->tdir_count == 1))
- {
- tif->tif_dir.td_planarconfig = PLANARCONFIG_CONTIG;
- TIFFWarningExtR(tif, module,
- "Planarconfig tag value assumed incorrect, "
- "assuming data is contig instead of chunky");
- }
- }
- }
- /*
- * Allocate directory structure and setup defaults.
- */
- if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS))
- {
- MissingRequired(tif, "ImageLength");
- goto bad;
- }
- /*
- * Second pass: extract other information.
- */
- for (di = 0, dp = dir; di < dircount; di++, dp++)
- {
- if (!dp->tdir_ignore)
- {
- switch (dp->tdir_tag)
- {
- case TIFFTAG_MINSAMPLEVALUE:
- case TIFFTAG_MAXSAMPLEVALUE:
- case TIFFTAG_BITSPERSAMPLE:
- case TIFFTAG_DATATYPE:
- case TIFFTAG_SAMPLEFORMAT:
- /*
- * The MinSampleValue, MaxSampleValue, BitsPerSample
- * DataType and SampleFormat tags are supposed to be
- * written as one value/sample, but some vendors
- * incorrectly write one value only -- so we accept
- * that as well (yuck). Other vendors write correct
- * value for NumberOfSamples, but incorrect one for
- * BitsPerSample and friends, and we will read this
- * too.
- */
- {
- uint16_t value;
- enum TIFFReadDirEntryErr err;
- err = TIFFReadDirEntryShort(tif, dp, &value);
- if (!EvaluateIFDdatasizeReading(tif, dp))
- goto bad;
- if (err == TIFFReadDirEntryErrCount)
- err =
- TIFFReadDirEntryPersampleShort(tif, dp, &value);
- if (err != TIFFReadDirEntryErrOk)
- {
- fip = TIFFFieldWithTag(tif, dp->tdir_tag);
- TIFFReadDirEntryOutputErr(
- tif, err, module,
- fip ? fip->field_name : "unknown tagname", 0);
- goto bad;
- }
- if (!TIFFSetField(tif, dp->tdir_tag, value))
- goto bad;
- if (dp->tdir_tag == TIFFTAG_BITSPERSAMPLE)
- bitspersample_read = TRUE;
- }
- break;
- case TIFFTAG_SMINSAMPLEVALUE:
- case TIFFTAG_SMAXSAMPLEVALUE:
- {
- double *data = NULL;
- enum TIFFReadDirEntryErr err;
- uint32_t saved_flags;
- int m;
- if (dp->tdir_count !=
- (uint64_t)tif->tif_dir.td_samplesperpixel)
- err = TIFFReadDirEntryErrCount;
- else
- err = TIFFReadDirEntryDoubleArray(tif, dp, &data);
- if (!EvaluateIFDdatasizeReading(tif, dp))
- goto bad;
- if (err != TIFFReadDirEntryErrOk)
- {
- fip = TIFFFieldWithTag(tif, dp->tdir_tag);
- TIFFReadDirEntryOutputErr(
- tif, err, module,
- fip ? fip->field_name : "unknown tagname", 0);
- goto bad;
- }
- saved_flags = tif->tif_flags;
- tif->tif_flags |= TIFF_PERSAMPLE;
- m = TIFFSetField(tif, dp->tdir_tag, data);
- tif->tif_flags = saved_flags;
- _TIFFfreeExt(tif, data);
- if (!m)
- goto bad;
- }
- break;
- case TIFFTAG_STRIPOFFSETS:
- case TIFFTAG_TILEOFFSETS:
- {
- switch (dp->tdir_type)
- {
- case TIFF_SHORT:
- case TIFF_LONG:
- case TIFF_LONG8:
- break;
- default:
- /* Warn except if directory typically created with
- * TIFFDeferStrileArrayWriting() */
- if (!(tif->tif_mode == O_RDWR &&
- dp->tdir_count == 0 && dp->tdir_type == 0 &&
- dp->tdir_offset.toff_long8 == 0))
- {
- fip = TIFFFieldWithTag(tif, dp->tdir_tag);
- TIFFWarningExtR(
- tif, module, "Invalid data type for tag %s",
- fip ? fip->field_name : "unknown tagname");
- }
- break;
- }
- _TIFFmemcpy(&(tif->tif_dir.td_stripoffset_entry), dp,
- sizeof(TIFFDirEntry));
- if (!EvaluateIFDdatasizeReading(tif, dp))
- goto bad;
- }
- break;
- case TIFFTAG_STRIPBYTECOUNTS:
- case TIFFTAG_TILEBYTECOUNTS:
- {
- switch (dp->tdir_type)
- {
- case TIFF_SHORT:
- case TIFF_LONG:
- case TIFF_LONG8:
- break;
- default:
- /* Warn except if directory typically created with
- * TIFFDeferStrileArrayWriting() */
- if (!(tif->tif_mode == O_RDWR &&
- dp->tdir_count == 0 && dp->tdir_type == 0 &&
- dp->tdir_offset.toff_long8 == 0))
- {
- fip = TIFFFieldWithTag(tif, dp->tdir_tag);
- TIFFWarningExtR(
- tif, module, "Invalid data type for tag %s",
- fip ? fip->field_name : "unknown tagname");
- }
- break;
- }
- _TIFFmemcpy(&(tif->tif_dir.td_stripbytecount_entry), dp,
- sizeof(TIFFDirEntry));
- if (!EvaluateIFDdatasizeReading(tif, dp))
- goto bad;
- }
- break;
- case TIFFTAG_COLORMAP:
- case TIFFTAG_TRANSFERFUNCTION:
- {
- enum TIFFReadDirEntryErr err;
- uint32_t countpersample;
- uint32_t countrequired;
- uint32_t incrementpersample;
- uint16_t *value = NULL;
- /* It would be dangerous to instantiate those tag values */
- /* since if td_bitspersample has not yet been read (due to
- */
- /* unordered tags), it could be read afterwards with a */
- /* values greater than the default one (1), which may cause
- */
- /* crashes in user code */
- if (!bitspersample_read)
- {
- fip = TIFFFieldWithTag(tif, dp->tdir_tag);
- TIFFWarningExtR(
- tif, module,
- "Ignoring %s since BitsPerSample tag not found",
- fip ? fip->field_name : "unknown tagname");
- continue;
- }
- /* ColorMap or TransferFunction for high bit */
- /* depths do not make much sense and could be */
- /* used as a denial of service vector */
- if (tif->tif_dir.td_bitspersample > 24)
- {
- fip = TIFFFieldWithTag(tif, dp->tdir_tag);
- TIFFWarningExtR(
- tif, module,
- "Ignoring %s because BitsPerSample=%" PRIu16 ">24",
- fip ? fip->field_name : "unknown tagname",
- tif->tif_dir.td_bitspersample);
- continue;
- }
- countpersample = (1U << tif->tif_dir.td_bitspersample);
- if ((dp->tdir_tag == TIFFTAG_TRANSFERFUNCTION) &&
- (dp->tdir_count == (uint64_t)countpersample))
- {
- countrequired = countpersample;
- incrementpersample = 0;
- }
- else
- {
- countrequired = 3 * countpersample;
- incrementpersample = countpersample;
- }
- if (dp->tdir_count != (uint64_t)countrequired)
- err = TIFFReadDirEntryErrCount;
- else
- err = TIFFReadDirEntryShortArray(tif, dp, &value);
- if (!EvaluateIFDdatasizeReading(tif, dp))
- goto bad;
- if (err != TIFFReadDirEntryErrOk)
- {
- fip = TIFFFieldWithTag(tif, dp->tdir_tag);
- TIFFReadDirEntryOutputErr(
- tif, err, module,
- fip ? fip->field_name : "unknown tagname", 1);
- }
- else
- {
- TIFFSetField(tif, dp->tdir_tag, value,
- value + incrementpersample,
- value + 2 * incrementpersample);
- _TIFFfreeExt(tif, value);
- }
- }
- break;
- /* BEGIN REV 4.0 COMPATIBILITY */
- case TIFFTAG_OSUBFILETYPE:
- {
- uint16_t valueo;
- uint32_t value;
- if (TIFFReadDirEntryShort(tif, dp, &valueo) ==
- TIFFReadDirEntryErrOk)
- {
- switch (valueo)
- {
- case OFILETYPE_REDUCEDIMAGE:
- value = FILETYPE_REDUCEDIMAGE;
- break;
- case OFILETYPE_PAGE:
- value = FILETYPE_PAGE;
- break;
- default:
- value = 0;
- break;
- }
- if (value != 0)
- TIFFSetField(tif, TIFFTAG_SUBFILETYPE, value);
- }
- }
- break;
- /* END REV 4.0 COMPATIBILITY */
- #if 0
- case TIFFTAG_EP_BATTERYLEVEL:
- /* TIFFTAG_EP_BATTERYLEVEL can be RATIONAL or ASCII.
- * LibTiff defines it as ASCII and converts RATIONAL to an
- * ASCII string. */
- switch (dp->tdir_type)
- {
- case TIFF_RATIONAL:
- {
- /* Read rational and convert to ASCII*/
- enum TIFFReadDirEntryErr err;
- TIFFRational_t rValue;
- err = TIFFReadDirEntryCheckedRationalDirect(
- tif, dp, &rValue);
- if (err != TIFFReadDirEntryErrOk)
- {
- fip = TIFFFieldWithTag(tif, dp->tdir_tag);
- TIFFReadDirEntryOutputErr(
- tif, err, module,
- fip ? fip->field_name : "unknown tagname",
- 1);
- }
- else
- {
- char szAux[32];
- snprintf(szAux, sizeof(szAux) - 1, "%d/%d",
- rValue.uNum, rValue.uDenom);
- TIFFSetField(tif, dp->tdir_tag, szAux);
- }
- }
- break;
- case TIFF_ASCII:
- (void)TIFFFetchNormalTag(tif, dp, TRUE);
- break;
- default:
- fip = TIFFFieldWithTag(tif, dp->tdir_tag);
- TIFFWarningExtR(tif, module,
- "Invalid data type for tag %s. "
- "ASCII or RATIONAL expected",
- fip ? fip->field_name
- : "unknown tagname");
- break;
- }
- break;
- #endif
- default:
- (void)TIFFFetchNormalTag(tif, dp, TRUE);
- break;
- } /* -- switch (dp->tdir_tag) -- */
- } /* -- if (!dp->tdir_ignore) */
- } /* -- for-loop -- */
- /* Evaluate final IFD data size. */
- CalcFinalIFDdatasizeReading(tif, dircount);
- /*
- * OJPEG hack:
- * - If a) compression is OJPEG, and b) photometric tag is missing,
- * then we consistently find that photometric should be YCbCr
- * - If a) compression is OJPEG, and b) photometric tag says it's RGB,
- * then we consistently find that the buggy implementation of the
- * buggy compression scheme matches photometric YCbCr instead.
- * - If a) compression is OJPEG, and b) bitspersample tag is missing,
- * then we consistently find bitspersample should be 8.
- * - If a) compression is OJPEG, b) samplesperpixel tag is missing,
- * and c) photometric is RGB or YCbCr, then we consistently find
- * samplesperpixel should be 3
- * - If a) compression is OJPEG, b) samplesperpixel tag is missing,
- * and c) photometric is MINISWHITE or MINISBLACK, then we consistently
- * find samplesperpixel should be 3
- */
- if (tif->tif_dir.td_compression == COMPRESSION_OJPEG)
- {
- if (!TIFFFieldSet(tif, FIELD_PHOTOMETRIC))
- {
- TIFFWarningExtR(
- tif, module,
- "Photometric tag is missing, assuming data is YCbCr");
- if (!TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR))
- goto bad;
- }
- else if (tif->tif_dir.td_photometric == PHOTOMETRIC_RGB)
- {
- tif->tif_dir.td_photometric = PHOTOMETRIC_YCBCR;
- TIFFWarningExtR(tif, module,
- "Photometric tag value assumed incorrect, "
- "assuming data is YCbCr instead of RGB");
- }
- if (!TIFFFieldSet(tif, FIELD_BITSPERSAMPLE))
- {
- TIFFWarningExtR(
- tif, module,
- "BitsPerSample tag is missing, assuming 8 bits per sample");
- if (!TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8))
- goto bad;
- }
- if (!TIFFFieldSet(tif, FIELD_SAMPLESPERPIXEL))
- {
- if (tif->tif_dir.td_photometric == PHOTOMETRIC_RGB)
- {
- TIFFWarningExtR(tif, module,
- "SamplesPerPixel tag is missing, "
- "assuming correct SamplesPerPixel value is 3");
- if (!TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3))
- goto bad;
- }
- if (tif->tif_dir.td_photometric == PHOTOMETRIC_YCBCR)
- {
- TIFFWarningExtR(tif, module,
- "SamplesPerPixel tag is missing, "
- "applying correct SamplesPerPixel value of 3");
- if (!TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3))
- goto bad;
- }
- else if ((tif->tif_dir.td_photometric == PHOTOMETRIC_MINISWHITE) ||
- (tif->tif_dir.td_photometric == PHOTOMETRIC_MINISBLACK))
- {
- /*
- * SamplesPerPixel tag is missing, but is not required
- * by spec. Assume correct SamplesPerPixel value of 1.
- */
- if (!TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1))
- goto bad;
- }
- }
- }
- /*
- * Setup appropriate structures (by strip or by tile)
- * We do that only after the above OJPEG hack which alters SamplesPerPixel
- * and thus influences the number of strips in the separate planarconfig.
- */
- if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS))
- {
- tif->tif_dir.td_nstrips = TIFFNumberOfStrips(tif);
- tif->tif_dir.td_tilewidth = tif->tif_dir.td_imagewidth;
- tif->tif_dir.td_tilelength = tif->tif_dir.td_rowsperstrip;
- tif->tif_dir.td_tiledepth = tif->tif_dir.td_imagedepth;
- tif->tif_flags &= ~TIFF_ISTILED;
- }
- else
- {
- tif->tif_dir.td_nstrips = TIFFNumberOfTiles(tif);
- tif->tif_flags |= TIFF_ISTILED;
- }
- if (!tif->tif_dir.td_nstrips)
- {
- TIFFErrorExtR(tif, module, "Cannot handle zero number of %s",
- isTiled(tif) ? "tiles" : "strips");
- goto bad;
- }
- tif->tif_dir.td_stripsperimage = tif->tif_dir.td_nstrips;
- if (tif->tif_dir.td_planarconfig == PLANARCONFIG_SEPARATE)
- tif->tif_dir.td_stripsperimage /= tif->tif_dir.td_samplesperpixel;
- if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS))
- {
- #ifdef OJPEG_SUPPORT
- if ((tif->tif_dir.td_compression == COMPRESSION_OJPEG) &&
- (isTiled(tif) == 0) && (tif->tif_dir.td_nstrips == 1))
- {
- /*
- * XXX: OJPEG hack.
- * If a) compression is OJPEG, b) it's not a tiled TIFF,
- * and c) the number of strips is 1,
- * then we tolerate the absence of stripoffsets tag,
- * because, presumably, all required data is in the
- * JpegInterchangeFormat stream.
- */
- TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
- }
- else
- #endif
- {
- MissingRequired(tif, isTiled(tif) ? "TileOffsets" : "StripOffsets");
- goto bad;
- }
- }
- if (tif->tif_mode == O_RDWR &&
- tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 &&
- tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
- tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
- tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 &&
- tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 &&
- tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
- tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
- tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0)
- {
- /* Directory typically created with TIFFDeferStrileArrayWriting() */
- TIFFSetupStrips(tif);
- }
- else if (!(tif->tif_flags & TIFF_DEFERSTRILELOAD))
- {
- if (tif->tif_dir.td_stripoffset_entry.tdir_tag != 0)
- {
- if (!TIFFFetchStripThing(tif, &(tif->tif_dir.td_stripoffset_entry),
- tif->tif_dir.td_nstrips,
- &tif->tif_dir.td_stripoffset_p))
- {
- goto bad;
- }
- }
- if (tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0)
- {
- if (!TIFFFetchStripThing(
- tif, &(tif->tif_dir.td_stripbytecount_entry),
- tif->tif_dir.td_nstrips, &tif->tif_dir.td_stripbytecount_p))
- {
- goto bad;
- }
- }
- }
- /*
- * Make sure all non-color channels are extrasamples.
- * If it's not the case, define them as such.
- */
- color_channels = _TIFFGetMaxColorChannels(tif->tif_dir.td_photometric);
- if (color_channels &&
- tif->tif_dir.td_samplesperpixel - tif->tif_dir.td_extrasamples >
- color_channels)
- {
- uint16_t old_extrasamples;
- uint16_t *new_sampleinfo;
- TIFFWarningExtR(
- tif, module,
- "Sum of Photometric type-related "
- "color channels and ExtraSamples doesn't match SamplesPerPixel. "
- "Defining non-color channels as ExtraSamples.");
- old_extrasamples = tif->tif_dir.td_extrasamples;
- tif->tif_dir.td_extrasamples =
- (uint16_t)(tif->tif_dir.td_samplesperpixel - color_channels);
- // sampleinfo should contain information relative to these new extra
- // samples
- new_sampleinfo = (uint16_t *)_TIFFcallocExt(
- tif, tif->tif_dir.td_extrasamples, sizeof(uint16_t));
- if (!new_sampleinfo)
- {
- TIFFErrorExtR(tif, module,
- "Failed to allocate memory for "
- "temporary new sampleinfo array "
- "(%" PRIu16 " 16 bit elements)",
- tif->tif_dir.td_extrasamples);
- goto bad;
- }
- if (old_extrasamples > 0)
- memcpy(new_sampleinfo, tif->tif_dir.td_sampleinfo,
- old_extrasamples * sizeof(uint16_t));
- _TIFFsetShortArrayExt(tif, &tif->tif_dir.td_sampleinfo, new_sampleinfo,
- tif->tif_dir.td_extrasamples);
- _TIFFfreeExt(tif, new_sampleinfo);
- }
- /*
- * Verify Palette image has a Colormap.
- */
- if (tif->tif_dir.td_photometric == PHOTOMETRIC_PALETTE &&
- !TIFFFieldSet(tif, FIELD_COLORMAP))
- {
- if (tif->tif_dir.td_bitspersample >= 8 &&
- tif->tif_dir.td_samplesperpixel == 3)
- tif->tif_dir.td_photometric = PHOTOMETRIC_RGB;
- else if (tif->tif_dir.td_bitspersample >= 8)
- tif->tif_dir.td_photometric = PHOTOMETRIC_MINISBLACK;
- else
- {
- MissingRequired(tif, "Colormap");
- goto bad;
- }
- }
- /*
- * OJPEG hack:
- * We do no further messing with strip/tile offsets/bytecounts in OJPEG
- * TIFFs
- */
- if (tif->tif_dir.td_compression != COMPRESSION_OJPEG)
- {
- /*
- * Attempt to deal with a missing StripByteCounts tag.
- */
- if (!TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS))
- {
- /*
- * Some manufacturers violate the spec by not giving
- * the size of the strips. In this case, assume there
- * is one uncompressed strip of data.
- */
- if ((tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG &&
- tif->tif_dir.td_nstrips > 1) ||
- (tif->tif_dir.td_planarconfig == PLANARCONFIG_SEPARATE &&
- tif->tif_dir.td_nstrips !=
- (uint32_t)tif->tif_dir.td_samplesperpixel))
- {
- MissingRequired(tif, "StripByteCounts");
- goto bad;
- }
- TIFFWarningExtR(
- tif, module,
- "TIFF directory is missing required "
- "\"StripByteCounts\" field, calculating from imagelength");
- if (EstimateStripByteCounts(tif, dir, dircount) < 0)
- goto bad;
- }
- else if (tif->tif_dir.td_nstrips == 1 &&
- !(tif->tif_flags & TIFF_ISTILED) && ByteCountLooksBad(tif))
- {
- /*
- * XXX: Plexus (and others) sometimes give a value of
- * zero for a tag when they don't know what the
- * correct value is! Try and handle the simple case
- * of estimating the size of a one strip image.
- */
- TIFFWarningExtR(tif, module,
- "Bogus \"StripByteCounts\" field, ignoring and "
- "calculating from imagelength");
- if (EstimateStripByteCounts(tif, dir, dircount) < 0)
- goto bad;
- }
- else if (!(tif->tif_flags & TIFF_DEFERSTRILELOAD) &&
- tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG &&
- tif->tif_dir.td_nstrips > 2 &&
- tif->tif_dir.td_compression == COMPRESSION_NONE &&
- TIFFGetStrileByteCount(tif, 0) !=
- TIFFGetStrileByteCount(tif, 1) &&
- TIFFGetStrileByteCount(tif, 0) != 0 &&
- TIFFGetStrileByteCount(tif, 1) != 0)
- {
- /*
- * XXX: Some vendors fill StripByteCount array with
- * absolutely wrong values (it can be equal to
- * StripOffset array, for example). Catch this case
- * here.
- *
- * We avoid this check if deferring strile loading
- * as it would always force us to load the strip/tile
- * information.
- */
- TIFFWarningExtR(tif, module,
- "Wrong \"StripByteCounts\" field, ignoring and "
- "calculating from imagelength");
- if (EstimateStripByteCounts(tif, dir, dircount) < 0)
- goto bad;
- }
- }
- if (dir)
- {
- _TIFFfreeExt(tif, dir);
- dir = NULL;
- }
- if (!TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE))
- {
- if (tif->tif_dir.td_bitspersample >= 16)
- tif->tif_dir.td_maxsamplevalue = 0xFFFF;
- else
- tif->tif_dir.td_maxsamplevalue =
- (uint16_t)((1L << tif->tif_dir.td_bitspersample) - 1);
- }
- #ifdef STRIPBYTECOUNTSORTED_UNUSED
- /*
- * XXX: We can optimize checking for the strip bounds using the sorted
- * bytecounts array. See also comments for TIFFAppendToStrip()
- * function in tif_write.c.
- */
- if (!(tif->tif_flags & TIFF_DEFERSTRILELOAD) && tif->tif_dir.td_nstrips > 1)
- {
- uint32_t strip;
- tif->tif_dir.td_stripbytecountsorted = 1;
- for (strip = 1; strip < tif->tif_dir.td_nstrips; strip++)
- {
- if (TIFFGetStrileOffset(tif, strip - 1) >
- TIFFGetStrileOffset(tif, strip))
- {
- tif->tif_dir.td_stripbytecountsorted = 0;
- break;
- }
- }
- }
- #endif
- /*
- * An opportunity for compression mode dependent tag fixup
- */
- (*tif->tif_fixuptags)(tif);
- /*
- * Some manufacturers make life difficult by writing
- * large amounts of uncompressed data as a single strip.
- * This is contrary to the recommendations of the spec.
- * The following makes an attempt at breaking such images
- * into strips closer to the recommended 8k bytes. A
- * side effect, however, is that the RowsPerStrip tag
- * value may be changed.
- */
- if ((tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG) &&
- (tif->tif_dir.td_nstrips == 1) &&
- (tif->tif_dir.td_compression == COMPRESSION_NONE) &&
- ((tif->tif_flags & (TIFF_STRIPCHOP | TIFF_ISTILED)) == TIFF_STRIPCHOP))
- {
- ChopUpSingleUncompressedStrip(tif);
- }
- /* There are also uncompressed striped files with strips larger than */
- /* 2 GB, which make them unfriendly with a lot of code. If possible, */
- /* try to expose smaller "virtual" strips. */
- if (tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG &&
- tif->tif_dir.td_compression == COMPRESSION_NONE &&
- (tif->tif_flags & (TIFF_STRIPCHOP | TIFF_ISTILED)) == TIFF_STRIPCHOP &&
- TIFFStripSize64(tif) > 0x7FFFFFFFUL)
- {
- TryChopUpUncompressedBigTiff(tif);
- }
- /*
- * Clear the dirty directory flag.
- */
- tif->tif_flags &= ~TIFF_DIRTYDIRECT;
- tif->tif_flags &= ~TIFF_DIRTYSTRIP;
- /*
- * Reinitialize i/o since we are starting on a new directory.
- */
- tif->tif_row = (uint32_t)-1;
- tif->tif_curstrip = (uint32_t)-1;
- tif->tif_col = (uint32_t)-1;
- tif->tif_curtile = (uint32_t)-1;
- tif->tif_tilesize = (tmsize_t)-1;
- tif->tif_scanlinesize = TIFFScanlineSize(tif);
- if (!tif->tif_scanlinesize)
- {
- TIFFErrorExtR(tif, module, "Cannot handle zero scanline size");
- return (0);
- }
- if (isTiled(tif))
- {
- tif->tif_tilesize = TIFFTileSize(tif);
- if (!tif->tif_tilesize)
- {
- TIFFErrorExtR(tif, module, "Cannot handle zero tile size");
- return (0);
- }
- }
- else
- {
- if (!TIFFStripSize(tif))
- {
- TIFFErrorExtR(tif, module, "Cannot handle zero strip size");
- return (0);
- }
- }
- return (1);
- bad:
- if (dir)
- _TIFFfreeExt(tif, dir);
- return (0);
- } /*-- TIFFReadDirectory() --*/
- static void TIFFReadDirectoryCheckOrder(TIFF *tif, TIFFDirEntry *dir,
- uint16_t dircount)
- {
- static const char module[] = "TIFFReadDirectoryCheckOrder";
- uint32_t m;
- uint16_t n;
- TIFFDirEntry *o;
- m = 0;
- for (n = 0, o = dir; n < dircount; n++, o++)
- {
- if (o->tdir_tag < m)
- {
- TIFFWarningExtR(tif, module,
- "Invalid TIFF directory; tags are not sorted in "
- "ascending order");
- break;
- }
- m = o->tdir_tag + 1;
- }
- }
- static TIFFDirEntry *TIFFReadDirectoryFindEntry(TIFF *tif, TIFFDirEntry *dir,
- uint16_t dircount,
- uint16_t tagid)
- {
- TIFFDirEntry *m;
- uint16_t n;
- (void)tif;
- for (m = dir, n = 0; n < dircount; m++, n++)
- {
- if (m->tdir_tag == tagid)
- return (m);
- }
- return (0);
- }
- static void TIFFReadDirectoryFindFieldInfo(TIFF *tif, uint16_t tagid,
- uint32_t *fii)
- {
- int32_t ma, mb, mc;
- ma = -1;
- mc = (int32_t)tif->tif_nfields;
- while (1)
- {
- if (ma + 1 == mc)
- {
- *fii = FAILED_FII;
- return;
- }
- mb = (ma + mc) / 2;
- if (tif->tif_fields[mb]->field_tag == (uint32_t)tagid)
- break;
- if (tif->tif_fields[mb]->field_tag < (uint32_t)tagid)
- ma = mb;
- else
- mc = mb;
- }
- while (1)
- {
- if (mb == 0)
- break;
- if (tif->tif_fields[mb - 1]->field_tag != (uint32_t)tagid)
- break;
- mb--;
- }
- *fii = mb;
- }
- /*
- * Read custom directory from the arbitrary offset.
- * The code is very similar to TIFFReadDirectory().
- */
- int TIFFReadCustomDirectory(TIFF *tif, toff_t diroff,
- const TIFFFieldArray *infoarray)
- {
- static const char module[] = "TIFFReadCustomDirectory";
- TIFFDirEntry *dir;
- uint16_t dircount;
- TIFFDirEntry *dp;
- uint16_t di;
- const TIFFField *fip;
- uint32_t fii;
- assert(infoarray != NULL);
- dircount = TIFFFetchDirectory(tif, diroff, &dir, NULL);
- if (!dircount)
- {
- TIFFErrorExtR(tif, module,
- "Failed to read custom directory at offset %" PRIu64,
- diroff);
- return 0;
- }
- TIFFReadDirectoryCheckOrder(tif, dir, dircount);
- /*
- * Mark duplicates of any tag to be ignored (bugzilla 1994)
- * to avoid certain pathological problems.
- */
- {
- TIFFDirEntry *ma;
- uint16_t mb;
- for (ma = dir, mb = 0; mb < dircount; ma++, mb++)
- {
- TIFFDirEntry *na;
- uint16_t nb;
- for (na = ma + 1, nb = mb + 1; nb < dircount; na++, nb++)
- {
- if (ma->tdir_tag == na->tdir_tag)
- {
- na->tdir_ignore = TRUE;
- }
- }
- }
- }
- /* Free any old stuff and reinit. */
- TIFFFreeDirectory(tif);
- /* Even if custom directories do not need the default settings of a standard
- * IFD, the pointer to the TIFFSetField() and TIFFGetField() (i.e.
- * tif->tif_tagmethods.vsetfield and tif->tif_tagmethods.vgetfield) need to
- * be initialized, which is done in TIFFDefaultDirectory().
- * After that, the field array for the custom tags needs to be setup again.
- */
- TIFFDefaultDirectory(tif);
- _TIFFSetupFields(tif, infoarray);
- /* Allocate arrays for offset values outside IFD entry for IFD data size
- * checking. Note: Counter are reset within TIFFFreeDirectory(). */
- tif->tif_dir.td_dirdatasize_offsets =
- (TIFFEntryOffsetAndLength *)_TIFFmallocExt(
- tif, dircount * sizeof(TIFFEntryOffsetAndLength));
- if (tif->tif_dir.td_dirdatasize_offsets == NULL)
- {
- TIFFErrorExtR(
- tif, module,
- "Failed to allocate memory for counting IFD data size at reading");
- if (dir)
- _TIFFfreeExt(tif, dir);
- return 0;
- }
- for (di = 0, dp = dir; di < dircount; di++, dp++)
- {
- TIFFReadDirectoryFindFieldInfo(tif, dp->tdir_tag, &fii);
- if (fii == FAILED_FII)
- {
- if (tif->tif_warn_about_unknown_tags)
- {
- TIFFWarningExtR(tif, module,
- "Unknown field with tag %" PRIu16 " (0x%" PRIx16
- ") encountered",
- dp->tdir_tag, dp->tdir_tag);
- }
- const TIFFField *fld = _TIFFCreateAnonField(
- tif, dp->tdir_tag, (TIFFDataType)dp->tdir_type);
- if (fld == NULL || !_TIFFMergeFields(tif, fld, 1))
- {
- if (tif->tif_warn_about_unknown_tags)
- {
- TIFFWarningExtR(
- tif, module,
- "Registering anonymous field with tag %" PRIu16
- " (0x%" PRIx16 ") failed",
- dp->tdir_tag, dp->tdir_tag);
- }
- dp->tdir_ignore = TRUE;
- }
- else
- {
- TIFFReadDirectoryFindFieldInfo(tif, dp->tdir_tag, &fii);
- assert(fii != FAILED_FII);
- }
- }
- if (!dp->tdir_ignore)
- {
- fip = tif->tif_fields[fii];
- if (fip->field_bit == FIELD_IGNORE)
- dp->tdir_ignore = TRUE;
- else
- {
- /* check data type */
- while ((fip->field_type != TIFF_ANY) &&
- (fip->field_type != dp->tdir_type))
- {
- fii++;
- if ((fii == tif->tif_nfields) ||
- (tif->tif_fields[fii]->field_tag !=
- (uint32_t)dp->tdir_tag))
- {
- fii = 0xFFFF;
- break;
- }
- fip = tif->tif_fields[fii];
- }
- if (fii == 0xFFFF)
- {
- TIFFWarningExtR(tif, module,
- "Wrong data type %" PRIu16
- " for \"%s\"; tag ignored",
- dp->tdir_type, fip->field_name);
- dp->tdir_ignore = TRUE;
- }
- else
- {
- /* check count if known in advance */
- if ((fip->field_readcount != TIFF_VARIABLE) &&
- (fip->field_readcount != TIFF_VARIABLE2))
- {
- uint32_t expected;
- if (fip->field_readcount == TIFF_SPP)
- expected =
- (uint32_t)tif->tif_dir.td_samplesperpixel;
- else
- expected = (uint32_t)fip->field_readcount;
- if (!CheckDirCount(tif, dp, expected))
- dp->tdir_ignore = TRUE;
- }
- }
- }
- if (!dp->tdir_ignore)
- {
- switch (dp->tdir_tag)
- {
- case EXIFTAG_SUBJECTDISTANCE:
- if (!TIFFFieldIsAnonymous(fip))
- {
- /* should only be called on a Exif directory */
- /* when exifFields[] is active */
- (void)TIFFFetchSubjectDistance(tif, dp);
- }
- else
- {
- (void)TIFFFetchNormalTag(tif, dp, TRUE);
- }
- break;
- default:
- (void)TIFFFetchNormalTag(tif, dp, TRUE);
- break;
- }
- } /*-- if (!dp->tdir_ignore) */
- }
- }
- /* Evaluate final IFD data size. */
- CalcFinalIFDdatasizeReading(tif, dircount);
- /* To be able to return from SubIFD or custom-IFD to main-IFD */
- tif->tif_setdirectory_force_absolute = TRUE;
- if (dir)
- _TIFFfreeExt(tif, dir);
- return 1;
- }
- /*
- * EXIF is important special case of custom IFD, so we have a special
- * function to read it.
- */
- int TIFFReadEXIFDirectory(TIFF *tif, toff_t diroff)
- {
- return TIFFReadCustomDirectory(tif, diroff, _TIFFGetExifFields());
- }
- /*
- *--: EXIF-GPS custom directory reading as another special case of custom IFD.
- */
- int TIFFReadGPSDirectory(TIFF *tif, toff_t diroff)
- {
- return TIFFReadCustomDirectory(tif, diroff, _TIFFGetGpsFields());
- }
- static int EstimateStripByteCounts(TIFF *tif, TIFFDirEntry *dir,
- uint16_t dircount)
- {
- static const char module[] = "EstimateStripByteCounts";
- TIFFDirEntry *dp;
- TIFFDirectory *td = &tif->tif_dir;
- uint32_t strip;
- /* Do not try to load stripbytecount as we will compute it */
- if (!_TIFFFillStrilesInternal(tif, 0))
- return -1;
- const uint64_t allocsize = (uint64_t)td->td_nstrips * sizeof(uint64_t);
- uint64_t filesize = 0;
- if (allocsize > 100 * 1024 * 1024)
- {
- /* Before allocating a huge amount of memory for corrupted files, check
- * if size of requested memory is not greater than file size. */
- filesize = TIFFGetFileSize(tif);
- if (allocsize > filesize)
- {
- TIFFWarningExtR(
- tif, module,
- "Requested memory size for StripByteCounts of %" PRIu64
- " is greater than filesize %" PRIu64 ". Memory not allocated",
- allocsize, filesize);
- return -1;
- }
- }
- if (td->td_stripbytecount_p)
- _TIFFfreeExt(tif, td->td_stripbytecount_p);
- td->td_stripbytecount_p = (uint64_t *)_TIFFCheckMalloc(
- tif, td->td_nstrips, sizeof(uint64_t), "for \"StripByteCounts\" array");
- if (td->td_stripbytecount_p == NULL)
- return -1;
- if (td->td_compression != COMPRESSION_NONE)
- {
- uint64_t space;
- uint16_t n;
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- space = sizeof(TIFFHeaderClassic) + 2 + dircount * 12 + 4;
- else
- space = sizeof(TIFFHeaderBig) + 8 + dircount * 20 + 8;
- /* calculate amount of space used by indirect values */
- for (dp = dir, n = dircount; n > 0; n--, dp++)
- {
- uint32_t typewidth;
- uint64_t datasize;
- typewidth = TIFFDataWidth((TIFFDataType)dp->tdir_type);
- if (typewidth == 0)
- {
- TIFFErrorExtR(
- tif, module,
- "Cannot determine size of unknown tag type %" PRIu16,
- dp->tdir_type);
- return -1;
- }
- if (dp->tdir_count > UINT64_MAX / typewidth)
- return -1;
- datasize = (uint64_t)typewidth * dp->tdir_count;
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- if (datasize <= 4)
- datasize = 0;
- }
- else
- {
- if (datasize <= 8)
- datasize = 0;
- }
- if (space > UINT64_MAX - datasize)
- return -1;
- space += datasize;
- }
- if (filesize == 0)
- filesize = TIFFGetFileSize(tif);
- if (filesize < space)
- /* we should perhaps return in error ? */
- space = filesize;
- else
- space = filesize - space;
- if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
- space /= td->td_samplesperpixel;
- for (strip = 0; strip < td->td_nstrips; strip++)
- td->td_stripbytecount_p[strip] = space;
- /*
- * This gross hack handles the case were the offset to
- * the last strip is past the place where we think the strip
- * should begin. Since a strip of data must be contiguous,
- * it's safe to assume that we've overestimated the amount
- * of data in the strip and trim this number back accordingly.
- */
- strip--;
- if (td->td_stripoffset_p[strip] >
- UINT64_MAX - td->td_stripbytecount_p[strip])
- return -1;
- if (td->td_stripoffset_p[strip] + td->td_stripbytecount_p[strip] >
- filesize)
- {
- if (td->td_stripoffset_p[strip] >= filesize)
- {
- /* Not sure what we should in that case... */
- td->td_stripbytecount_p[strip] = 0;
- }
- else
- {
- td->td_stripbytecount_p[strip] =
- filesize - td->td_stripoffset_p[strip];
- }
- }
- }
- else if (isTiled(tif))
- {
- uint64_t bytespertile = TIFFTileSize64(tif);
- for (strip = 0; strip < td->td_nstrips; strip++)
- td->td_stripbytecount_p[strip] = bytespertile;
- }
- else
- {
- uint64_t rowbytes = TIFFScanlineSize64(tif);
- uint32_t rowsperstrip = td->td_imagelength / td->td_stripsperimage;
- for (strip = 0; strip < td->td_nstrips; strip++)
- {
- if (rowbytes > 0 && rowsperstrip > UINT64_MAX / rowbytes)
- return -1;
- td->td_stripbytecount_p[strip] = rowbytes * rowsperstrip;
- }
- }
- TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
- if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP))
- td->td_rowsperstrip = td->td_imagelength;
- return 1;
- }
- static void MissingRequired(TIFF *tif, const char *tagname)
- {
- static const char module[] = "MissingRequired";
- TIFFErrorExtR(tif, module,
- "TIFF directory is missing required \"%s\" field", tagname);
- }
- static unsigned long hashFuncOffsetToNumber(const void *elt)
- {
- const TIFFOffsetAndDirNumber *offsetAndDirNumber =
- (const TIFFOffsetAndDirNumber *)elt;
- const uint32_t hash = (uint32_t)(offsetAndDirNumber->offset >> 32) ^
- ((uint32_t)offsetAndDirNumber->offset & 0xFFFFFFFFU);
- return hash;
- }
- static bool equalFuncOffsetToNumber(const void *elt1, const void *elt2)
- {
- const TIFFOffsetAndDirNumber *offsetAndDirNumber1 =
- (const TIFFOffsetAndDirNumber *)elt1;
- const TIFFOffsetAndDirNumber *offsetAndDirNumber2 =
- (const TIFFOffsetAndDirNumber *)elt2;
- return offsetAndDirNumber1->offset == offsetAndDirNumber2->offset;
- }
- static unsigned long hashFuncNumberToOffset(const void *elt)
- {
- const TIFFOffsetAndDirNumber *offsetAndDirNumber =
- (const TIFFOffsetAndDirNumber *)elt;
- return offsetAndDirNumber->dirNumber;
- }
- static bool equalFuncNumberToOffset(const void *elt1, const void *elt2)
- {
- const TIFFOffsetAndDirNumber *offsetAndDirNumber1 =
- (const TIFFOffsetAndDirNumber *)elt1;
- const TIFFOffsetAndDirNumber *offsetAndDirNumber2 =
- (const TIFFOffsetAndDirNumber *)elt2;
- return offsetAndDirNumber1->dirNumber == offsetAndDirNumber2->dirNumber;
- }
- /*
- * Check the directory number and offset against the list of already seen
- * directory numbers and offsets. This is a trick to prevent IFD looping.
- * The one can create TIFF file with looped directory pointers. We will
- * maintain a list of already seen directories and check every IFD offset
- * and its IFD number against that list. However, the offset of an IFD number
- * can change - e.g. when writing updates to file.
- * Returns 1 if all is ok; 0 if last directory or IFD loop is encountered,
- * or an error has occurred.
- */
- int _TIFFCheckDirNumberAndOffset(TIFF *tif, tdir_t dirn, uint64_t diroff)
- {
- if (diroff == 0) /* no more directories */
- return 0;
- if (tif->tif_map_dir_offset_to_number == NULL)
- {
- tif->tif_map_dir_offset_to_number = TIFFHashSetNew(
- hashFuncOffsetToNumber, equalFuncOffsetToNumber, free);
- if (tif->tif_map_dir_offset_to_number == NULL)
- {
- TIFFErrorExtR(tif, "_TIFFCheckDirNumberAndOffset",
- "Not enough memory");
- return 1;
- }
- }
- if (tif->tif_map_dir_number_to_offset == NULL)
- {
- /* No free callback for this map, as it shares the same items as
- * tif->tif_map_dir_offset_to_number. */
- tif->tif_map_dir_number_to_offset = TIFFHashSetNew(
- hashFuncNumberToOffset, equalFuncNumberToOffset, NULL);
- if (tif->tif_map_dir_number_to_offset == NULL)
- {
- TIFFErrorExtR(tif, "_TIFFCheckDirNumberAndOffset",
- "Not enough memory");
- return 1;
- }
- }
- /* Check if offset is already in the list:
- * - yes: check, if offset is at the same IFD number - if not, it is an IFD
- * loop
- * - no: add to list or update offset at that IFD number
- */
- TIFFOffsetAndDirNumber entry;
- entry.offset = diroff;
- entry.dirNumber = dirn;
- TIFFOffsetAndDirNumber *foundEntry =
- (TIFFOffsetAndDirNumber *)TIFFHashSetLookup(
- tif->tif_map_dir_offset_to_number, &entry);
- if (foundEntry)
- {
- if (foundEntry->dirNumber == dirn)
- {
- return 1;
- }
- else
- {
- TIFFWarningExtR(tif, "_TIFFCheckDirNumberAndOffset",
- "TIFF directory %d has IFD looping to directory %u "
- "at offset 0x%" PRIx64 " (%" PRIu64 ")",
- (int)dirn - 1, foundEntry->dirNumber, diroff,
- diroff);
- return 0;
- }
- }
- /* Check if offset of an IFD has been changed and update offset of that IFD
- * number. */
- foundEntry = (TIFFOffsetAndDirNumber *)TIFFHashSetLookup(
- tif->tif_map_dir_number_to_offset, &entry);
- if (foundEntry)
- {
- if (foundEntry->offset != diroff)
- {
- TIFFOffsetAndDirNumber entryOld;
- entryOld.offset = foundEntry->offset;
- entryOld.dirNumber = dirn;
- /* We must remove first from tif_map_dir_number_to_offset as the */
- /* entry is owned (and thus freed) by */
- /* tif_map_dir_offset_to_number */
- TIFFOffsetAndDirNumber *foundEntryOld =
- (TIFFOffsetAndDirNumber *)TIFFHashSetLookup(
- tif->tif_map_dir_number_to_offset, &entryOld);
- if (foundEntryOld)
- {
- TIFFHashSetRemove(tif->tif_map_dir_number_to_offset,
- foundEntryOld);
- }
- foundEntryOld = (TIFFOffsetAndDirNumber *)TIFFHashSetLookup(
- tif->tif_map_dir_offset_to_number, &entryOld);
- if (foundEntryOld)
- {
- TIFFHashSetRemove(tif->tif_map_dir_offset_to_number,
- foundEntryOld);
- }
- TIFFOffsetAndDirNumber *entryPtr = (TIFFOffsetAndDirNumber *)malloc(
- sizeof(TIFFOffsetAndDirNumber));
- if (entryPtr == NULL)
- {
- return 0;
- }
- /* Add IFD offset and dirn to IFD directory list */
- *entryPtr = entry;
- if (!TIFFHashSetInsert(tif->tif_map_dir_offset_to_number, entryPtr))
- {
- TIFFErrorExtR(
- tif, "_TIFFCheckDirNumberAndOffset",
- "Insertion in tif_map_dir_offset_to_number failed");
- return 0;
- }
- if (!TIFFHashSetInsert(tif->tif_map_dir_number_to_offset, entryPtr))
- {
- TIFFErrorExtR(
- tif, "_TIFFCheckDirNumberAndOffset",
- "Insertion in tif_map_dir_number_to_offset failed");
- return 0;
- }
- }
- return 1;
- }
- /* Arbitrary (hopefully big enough) limit */
- if (TIFFHashSetSize(tif->tif_map_dir_offset_to_number) >=
- TIFF_MAX_DIR_COUNT)
- {
- TIFFErrorExtR(tif, "_TIFFCheckDirNumberAndOffset",
- "Cannot handle more than %u TIFF directories",
- TIFF_MAX_DIR_COUNT);
- return 0;
- }
- TIFFOffsetAndDirNumber *entryPtr =
- (TIFFOffsetAndDirNumber *)malloc(sizeof(TIFFOffsetAndDirNumber));
- if (entryPtr == NULL)
- {
- TIFFErrorExtR(tif, "_TIFFCheckDirNumberAndOffset",
- "malloc(sizeof(TIFFOffsetAndDirNumber)) failed");
- return 0;
- }
- /* Add IFD offset and dirn to IFD directory list */
- *entryPtr = entry;
- if (!TIFFHashSetInsert(tif->tif_map_dir_offset_to_number, entryPtr))
- {
- TIFFErrorExtR(tif, "_TIFFCheckDirNumberAndOffset",
- "Insertion in tif_map_dir_offset_to_number failed");
- return 0;
- }
- if (!TIFFHashSetInsert(tif->tif_map_dir_number_to_offset, entryPtr))
- {
- TIFFErrorExtR(tif, "_TIFFCheckDirNumberAndOffset",
- "Insertion in tif_map_dir_number_to_offset failed");
- return 0;
- }
- return 1;
- } /* --- _TIFFCheckDirNumberAndOffset() ---*/
- /*
- * Retrieve the matching IFD directory number of a given IFD offset
- * from the list of directories already seen.
- * Returns 1 if the offset was in the list and the directory number
- * can be returned.
- * Otherwise returns 0 or if an error occurred.
- */
- int _TIFFGetDirNumberFromOffset(TIFF *tif, uint64_t diroff, tdir_t *dirn)
- {
- if (diroff == 0) /* no more directories */
- return 0;
- /* Check if offset is already in the list and return matching directory
- * number. Otherwise update IFD list using TIFFNumberOfDirectories() and
- * search again in IFD list.
- */
- if (tif->tif_map_dir_offset_to_number == NULL)
- return 0;
- TIFFOffsetAndDirNumber entry;
- entry.offset = diroff;
- entry.dirNumber = 0; /* not used */
- TIFFOffsetAndDirNumber *foundEntry =
- (TIFFOffsetAndDirNumber *)TIFFHashSetLookup(
- tif->tif_map_dir_offset_to_number, &entry);
- if (foundEntry)
- {
- *dirn = foundEntry->dirNumber;
- return 1;
- }
- /* This updates the directory list for all main-IFDs in the file. */
- TIFFNumberOfDirectories(tif);
- foundEntry = (TIFFOffsetAndDirNumber *)TIFFHashSetLookup(
- tif->tif_map_dir_offset_to_number, &entry);
- if (foundEntry)
- {
- *dirn = foundEntry->dirNumber;
- return 1;
- }
- return 0;
- } /*--- _TIFFGetDirNumberFromOffset() ---*/
- /*
- * Retrieve the matching IFD directory offset of a given IFD number
- * from the list of directories already seen.
- * Returns 1 if the offset was in the list of already seen IFDs and the
- * directory offset can be returned. The directory list is not updated.
- * Otherwise returns 0 or if an error occurred.
- */
- int _TIFFGetOffsetFromDirNumber(TIFF *tif, tdir_t dirn, uint64_t *diroff)
- {
- if (tif->tif_map_dir_number_to_offset == NULL)
- return 0;
- TIFFOffsetAndDirNumber entry;
- entry.offset = 0; /* not used */
- entry.dirNumber = dirn;
- TIFFOffsetAndDirNumber *foundEntry =
- (TIFFOffsetAndDirNumber *)TIFFHashSetLookup(
- tif->tif_map_dir_number_to_offset, &entry);
- if (foundEntry)
- {
- *diroff = foundEntry->offset;
- return 1;
- }
- return 0;
- } /*--- _TIFFGetOffsetFromDirNumber() ---*/
- /*
- * Remove an entry from the directory list of already seen directories
- * by directory offset.
- * If an entry is to be removed from the list, it is also okay if the entry
- * is not in the list or the list does not exist.
- */
- int _TIFFRemoveEntryFromDirectoryListByOffset(TIFF *tif, uint64_t diroff)
- {
- if (tif->tif_map_dir_offset_to_number == NULL)
- return 1;
- TIFFOffsetAndDirNumber entryOld;
- entryOld.offset = diroff;
- entryOld.dirNumber = 0;
- /* We must remove first from tif_map_dir_number_to_offset as the
- * entry is owned (and thus freed) by tif_map_dir_offset_to_number.
- * However, we need firstly to find the directory number from offset. */
- TIFFOffsetAndDirNumber *foundEntryOldOff =
- (TIFFOffsetAndDirNumber *)TIFFHashSetLookup(
- tif->tif_map_dir_offset_to_number, &entryOld);
- if (foundEntryOldOff)
- {
- entryOld.dirNumber = foundEntryOldOff->dirNumber;
- if (tif->tif_map_dir_number_to_offset != NULL)
- {
- TIFFOffsetAndDirNumber *foundEntryOldDir =
- (TIFFOffsetAndDirNumber *)TIFFHashSetLookup(
- tif->tif_map_dir_number_to_offset, &entryOld);
- if (foundEntryOldDir)
- {
- TIFFHashSetRemove(tif->tif_map_dir_number_to_offset,
- foundEntryOldDir);
- TIFFHashSetRemove(tif->tif_map_dir_offset_to_number,
- foundEntryOldOff);
- return 1;
- }
- }
- else
- {
- TIFFErrorExtR(tif, "_TIFFRemoveEntryFromDirectoryListByOffset",
- "Unexpectedly tif_map_dir_number_to_offset is "
- "missing but tif_map_dir_offset_to_number exists.");
- return 0;
- }
- }
- return 1;
- } /*--- _TIFFRemoveEntryFromDirectoryListByOffset() ---*/
- /*
- * Check the count field of a directory entry against a known value. The
- * caller is expected to skip/ignore the tag if there is a mismatch.
- */
- static int CheckDirCount(TIFF *tif, TIFFDirEntry *dir, uint32_t count)
- {
- if ((uint64_t)count > dir->tdir_count)
- {
- const TIFFField *fip = TIFFFieldWithTag(tif, dir->tdir_tag);
- TIFFWarningExtR(tif, tif->tif_name,
- "incorrect count for field \"%s\" (%" PRIu64
- ", expecting %" PRIu32 "); tag ignored",
- fip ? fip->field_name : "unknown tagname",
- dir->tdir_count, count);
- return (0);
- }
- else if ((uint64_t)count < dir->tdir_count)
- {
- const TIFFField *fip = TIFFFieldWithTag(tif, dir->tdir_tag);
- TIFFWarningExtR(tif, tif->tif_name,
- "incorrect count for field \"%s\" (%" PRIu64
- ", expecting %" PRIu32 "); tag trimmed",
- fip ? fip->field_name : "unknown tagname",
- dir->tdir_count, count);
- dir->tdir_count = count;
- return (1);
- }
- return (1);
- }
- /*
- * Read IFD structure from the specified offset. If the pointer to
- * nextdiroff variable has been specified, read it too. Function returns a
- * number of fields in the directory or 0 if failed.
- */
- static uint16_t TIFFFetchDirectory(TIFF *tif, uint64_t diroff,
- TIFFDirEntry **pdir, uint64_t *nextdiroff)
- {
- static const char module[] = "TIFFFetchDirectory";
- void *origdir;
- uint16_t dircount16;
- uint32_t dirsize;
- TIFFDirEntry *dir;
- uint8_t *ma;
- TIFFDirEntry *mb;
- uint16_t n;
- assert(pdir);
- tif->tif_diroff = diroff;
- if (nextdiroff)
- *nextdiroff = 0;
- if (!isMapped(tif))
- {
- if (!SeekOK(tif, tif->tif_diroff))
- {
- TIFFErrorExtR(tif, module,
- "%s: Seek error accessing TIFF directory",
- tif->tif_name);
- return 0;
- }
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- if (!ReadOK(tif, &dircount16, sizeof(uint16_t)))
- {
- TIFFErrorExtR(tif, module,
- "%s: Can not read TIFF directory count",
- tif->tif_name);
- return 0;
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(&dircount16);
- if (dircount16 > 4096)
- {
- TIFFErrorExtR(tif, module,
- "Sanity check on directory count failed, this is "
- "probably not a valid IFD offset");
- return 0;
- }
- dirsize = 12;
- }
- else
- {
- uint64_t dircount64;
- if (!ReadOK(tif, &dircount64, sizeof(uint64_t)))
- {
- TIFFErrorExtR(tif, module,
- "%s: Can not read TIFF directory count",
- tif->tif_name);
- return 0;
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(&dircount64);
- if (dircount64 > 4096)
- {
- TIFFErrorExtR(tif, module,
- "Sanity check on directory count failed, this is "
- "probably not a valid IFD offset");
- return 0;
- }
- dircount16 = (uint16_t)dircount64;
- dirsize = 20;
- }
- origdir = _TIFFCheckMalloc(tif, dircount16, dirsize,
- "to read TIFF directory");
- if (origdir == NULL)
- return 0;
- if (!ReadOK(tif, origdir, (tmsize_t)(dircount16 * dirsize)))
- {
- TIFFErrorExtR(tif, module, "%.100s: Can not read TIFF directory",
- tif->tif_name);
- _TIFFfreeExt(tif, origdir);
- return 0;
- }
- /*
- * Read offset to next directory for sequential scans if
- * needed.
- */
- if (nextdiroff)
- {
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- uint32_t nextdiroff32;
- if (!ReadOK(tif, &nextdiroff32, sizeof(uint32_t)))
- nextdiroff32 = 0;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&nextdiroff32);
- *nextdiroff = nextdiroff32;
- }
- else
- {
- if (!ReadOK(tif, nextdiroff, sizeof(uint64_t)))
- *nextdiroff = 0;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(nextdiroff);
- }
- }
- }
- else
- {
- tmsize_t m;
- tmsize_t off;
- if (tif->tif_diroff > (uint64_t)INT64_MAX)
- {
- TIFFErrorExtR(tif, module, "Can not read TIFF directory count");
- return (0);
- }
- off = (tmsize_t)tif->tif_diroff;
- /*
- * Check for integer overflow when validating the dir_off,
- * otherwise a very high offset may cause an OOB read and
- * crash the client. Make two comparisons instead of
- *
- * off + sizeof(uint16_t) > tif->tif_size
- *
- * to avoid overflow.
- */
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- m = off + sizeof(uint16_t);
- if ((m < off) || (m < (tmsize_t)sizeof(uint16_t)) ||
- (m > tif->tif_size))
- {
- TIFFErrorExtR(tif, module, "Can not read TIFF directory count");
- return 0;
- }
- else
- {
- _TIFFmemcpy(&dircount16, tif->tif_base + off, sizeof(uint16_t));
- }
- off += sizeof(uint16_t);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(&dircount16);
- if (dircount16 > 4096)
- {
- TIFFErrorExtR(tif, module,
- "Sanity check on directory count failed, this is "
- "probably not a valid IFD offset");
- return 0;
- }
- dirsize = 12;
- }
- else
- {
- uint64_t dircount64;
- m = off + sizeof(uint64_t);
- if ((m < off) || (m < (tmsize_t)sizeof(uint64_t)) ||
- (m > tif->tif_size))
- {
- TIFFErrorExtR(tif, module, "Can not read TIFF directory count");
- return 0;
- }
- else
- {
- _TIFFmemcpy(&dircount64, tif->tif_base + off, sizeof(uint64_t));
- }
- off += sizeof(uint64_t);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(&dircount64);
- if (dircount64 > 4096)
- {
- TIFFErrorExtR(tif, module,
- "Sanity check on directory count failed, this is "
- "probably not a valid IFD offset");
- return 0;
- }
- dircount16 = (uint16_t)dircount64;
- dirsize = 20;
- }
- if (dircount16 == 0)
- {
- TIFFErrorExtR(tif, module,
- "Sanity check on directory count failed, zero tag "
- "directories not supported");
- return 0;
- }
- /* Before allocating a huge amount of memory for corrupted files, check
- * if size of requested memory is not greater than file size. */
- uint64_t filesize = TIFFGetFileSize(tif);
- uint64_t allocsize = (uint64_t)dircount16 * dirsize;
- if (allocsize > filesize)
- {
- TIFFWarningExtR(
- tif, module,
- "Requested memory size for TIFF directory of %" PRIu64
- " is greater than filesize %" PRIu64
- ". Memory not allocated, TIFF directory not read",
- allocsize, filesize);
- return 0;
- }
- origdir = _TIFFCheckMalloc(tif, dircount16, dirsize,
- "to read TIFF directory");
- if (origdir == NULL)
- return 0;
- m = off + dircount16 * dirsize;
- if ((m < off) || (m < (tmsize_t)(dircount16 * dirsize)) ||
- (m > tif->tif_size))
- {
- TIFFErrorExtR(tif, module, "Can not read TIFF directory");
- _TIFFfreeExt(tif, origdir);
- return 0;
- }
- else
- {
- _TIFFmemcpy(origdir, tif->tif_base + off, dircount16 * dirsize);
- }
- if (nextdiroff)
- {
- off += dircount16 * dirsize;
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- uint32_t nextdiroff32;
- m = off + sizeof(uint32_t);
- if ((m < off) || (m < (tmsize_t)sizeof(uint32_t)) ||
- (m > tif->tif_size))
- nextdiroff32 = 0;
- else
- _TIFFmemcpy(&nextdiroff32, tif->tif_base + off,
- sizeof(uint32_t));
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&nextdiroff32);
- *nextdiroff = nextdiroff32;
- }
- else
- {
- m = off + sizeof(uint64_t);
- if ((m < off) || (m < (tmsize_t)sizeof(uint64_t)) ||
- (m > tif->tif_size))
- *nextdiroff = 0;
- else
- _TIFFmemcpy(nextdiroff, tif->tif_base + off,
- sizeof(uint64_t));
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(nextdiroff);
- }
- }
- }
- /* No check against filesize needed here because "dir" should have same size
- * than "origdir" checked above. */
- dir = (TIFFDirEntry *)_TIFFCheckMalloc(
- tif, dircount16, sizeof(TIFFDirEntry), "to read TIFF directory");
- if (dir == 0)
- {
- _TIFFfreeExt(tif, origdir);
- return 0;
- }
- ma = (uint8_t *)origdir;
- mb = dir;
- for (n = 0; n < dircount16; n++)
- {
- mb->tdir_ignore = FALSE;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((uint16_t *)ma);
- mb->tdir_tag = *(uint16_t *)ma;
- ma += sizeof(uint16_t);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((uint16_t *)ma);
- mb->tdir_type = *(uint16_t *)ma;
- ma += sizeof(uint16_t);
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong((uint32_t *)ma);
- mb->tdir_count = (uint64_t)(*(uint32_t *)ma);
- ma += sizeof(uint32_t);
- mb->tdir_offset.toff_long8 = 0;
- *(uint32_t *)(&mb->tdir_offset) = *(uint32_t *)ma;
- ma += sizeof(uint32_t);
- }
- else
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8((uint64_t *)ma);
- mb->tdir_count = TIFFReadUInt64(ma);
- ma += sizeof(uint64_t);
- mb->tdir_offset.toff_long8 = TIFFReadUInt64(ma);
- ma += sizeof(uint64_t);
- }
- mb++;
- }
- _TIFFfreeExt(tif, origdir);
- *pdir = dir;
- return dircount16;
- }
- /*
- * Fetch a tag that is not handled by special case code.
- */
- static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover)
- {
- static const char module[] = "TIFFFetchNormalTag";
- enum TIFFReadDirEntryErr err;
- uint32_t fii;
- const TIFFField *fip = NULL;
- TIFFReadDirectoryFindFieldInfo(tif, dp->tdir_tag, &fii);
- if (fii == FAILED_FII)
- {
- TIFFErrorExtR(tif, "TIFFFetchNormalTag",
- "No definition found for tag %" PRIu16, dp->tdir_tag);
- return 0;
- }
- fip = tif->tif_fields[fii];
- assert(fip != NULL); /* should not happen */
- assert(fip->set_get_field_type !=
- TIFF_SETGET_OTHER); /* if so, we shouldn't arrive here but deal with
- this in specialized code */
- assert(fip->set_get_field_type !=
- TIFF_SETGET_INT); /* if so, we shouldn't arrive here as this is only
- the case for pseudo-tags */
- err = TIFFReadDirEntryErrOk;
- switch (fip->set_get_field_type)
- {
- case TIFF_SETGET_UNDEFINED:
- TIFFErrorExtR(
- tif, "TIFFFetchNormalTag",
- "Defined set_get_field_type of custom tag %u (%s) is "
- "TIFF_SETGET_UNDEFINED and thus tag is not read from file",
- fip->field_tag, fip->field_name);
- break;
- case TIFF_SETGET_ASCII:
- {
- uint8_t *data;
- assert(fip->field_passcount == 0);
- err = TIFFReadDirEntryByteArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- size_t mb = 0;
- int n;
- if (data != NULL)
- {
- if (dp->tdir_count > 0 && data[dp->tdir_count - 1] == 0)
- {
- /* optimization: if data is known to be 0 terminated, we
- * can use strlen() */
- mb = strlen((const char *)data);
- }
- else
- {
- /* general case. equivalent to non-portable */
- /* mb = strnlen((const char*)data,
- * (uint32_t)dp->tdir_count); */
- uint8_t *ma = data;
- while (mb < (uint32_t)dp->tdir_count)
- {
- if (*ma == 0)
- break;
- ma++;
- mb++;
- }
- }
- }
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != NULL)
- _TIFFfreeExt(tif, data);
- return (0);
- }
- if (mb + 1 < (uint32_t)dp->tdir_count)
- TIFFWarningExtR(
- tif, module,
- "ASCII value for tag \"%s\" contains null byte in "
- "value; value incorrectly truncated during reading due "
- "to implementation limitations",
- fip->field_name);
- else if (mb + 1 > (uint32_t)dp->tdir_count)
- {
- TIFFWarningExtR(tif, module,
- "ASCII value for tag \"%s\" does not end "
- "in null byte. Forcing it to be null",
- fip->field_name);
- /* TIFFReadDirEntryArrayWithLimit() ensures this can't be
- * larger than MAX_SIZE_TAG_DATA */
- assert((uint32_t)dp->tdir_count + 1 == dp->tdir_count + 1);
- uint8_t *o =
- _TIFFmallocExt(tif, (uint32_t)dp->tdir_count + 1);
- if (o == NULL)
- {
- if (data != NULL)
- _TIFFfreeExt(tif, data);
- return (0);
- }
- if (dp->tdir_count > 0)
- {
- _TIFFmemcpy(o, data, (uint32_t)dp->tdir_count);
- }
- o[(uint32_t)dp->tdir_count] = 0;
- if (data != 0)
- _TIFFfreeExt(tif, data);
- data = o;
- }
- n = TIFFSetField(tif, dp->tdir_tag, data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!n)
- return (0);
- }
- }
- break;
- case TIFF_SETGET_UINT8:
- {
- uint8_t data = 0;
- assert(fip->field_readcount == 1);
- assert(fip->field_passcount == 0);
- err = TIFFReadDirEntryByte(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!TIFFSetField(tif, dp->tdir_tag, data))
- return (0);
- }
- }
- break;
- case TIFF_SETGET_SINT8:
- {
- int8_t data = 0;
- assert(fip->field_readcount == 1);
- assert(fip->field_passcount == 0);
- err = TIFFReadDirEntrySbyte(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!TIFFSetField(tif, dp->tdir_tag, data))
- return (0);
- }
- }
- break;
- case TIFF_SETGET_UINT16:
- {
- uint16_t data;
- assert(fip->field_readcount == 1);
- assert(fip->field_passcount == 0);
- err = TIFFReadDirEntryShort(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!TIFFSetField(tif, dp->tdir_tag, data))
- return (0);
- }
- }
- break;
- case TIFF_SETGET_SINT16:
- {
- int16_t data;
- assert(fip->field_readcount == 1);
- assert(fip->field_passcount == 0);
- err = TIFFReadDirEntrySshort(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!TIFFSetField(tif, dp->tdir_tag, data))
- return (0);
- }
- }
- break;
- case TIFF_SETGET_UINT32:
- {
- uint32_t data;
- assert(fip->field_readcount == 1);
- assert(fip->field_passcount == 0);
- err = TIFFReadDirEntryLong(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!TIFFSetField(tif, dp->tdir_tag, data))
- return (0);
- }
- }
- break;
- case TIFF_SETGET_SINT32:
- {
- int32_t data;
- assert(fip->field_readcount == 1);
- assert(fip->field_passcount == 0);
- err = TIFFReadDirEntrySlong(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!TIFFSetField(tif, dp->tdir_tag, data))
- return (0);
- }
- }
- break;
- case TIFF_SETGET_UINT64:
- {
- uint64_t data;
- assert(fip->field_readcount == 1);
- assert(fip->field_passcount == 0);
- err = TIFFReadDirEntryLong8(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- return 0;
- if (!TIFFSetField(tif, dp->tdir_tag, data))
- return (0);
- }
- }
- break;
- case TIFF_SETGET_SINT64:
- {
- int64_t data;
- assert(fip->field_readcount == 1);
- assert(fip->field_passcount == 0);
- err = TIFFReadDirEntrySlong8(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- return 0;
- if (!TIFFSetField(tif, dp->tdir_tag, data))
- return (0);
- }
- }
- break;
- case TIFF_SETGET_FLOAT:
- {
- float data;
- assert(fip->field_readcount == 1);
- assert(fip->field_passcount == 0);
- err = TIFFReadDirEntryFloat(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- return 0;
- if (!TIFFSetField(tif, dp->tdir_tag, data))
- return (0);
- }
- }
- break;
- case TIFF_SETGET_DOUBLE:
- {
- double data;
- assert(fip->field_readcount == 1);
- assert(fip->field_passcount == 0);
- err = TIFFReadDirEntryDouble(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- return 0;
- if (!TIFFSetField(tif, dp->tdir_tag, data))
- return (0);
- }
- }
- break;
- case TIFF_SETGET_IFD8:
- {
- uint64_t data;
- assert(fip->field_readcount == 1);
- assert(fip->field_passcount == 0);
- err = TIFFReadDirEntryIfd8(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- return 0;
- if (!TIFFSetField(tif, dp->tdir_tag, data))
- return (0);
- }
- }
- break;
- case TIFF_SETGET_UINT16_PAIR:
- {
- uint16_t *data;
- assert(fip->field_readcount == 2);
- assert(fip->field_passcount == 0);
- if (dp->tdir_count != 2)
- {
- TIFFWarningExtR(tif, module,
- "incorrect count for field \"%s\", expected 2, "
- "got %" PRIu64,
- fip->field_name, dp->tdir_count);
- return (0);
- }
- err = TIFFReadDirEntryShortArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- int m;
- assert(data); /* avoid CLang static Analyzer false positive */
- m = TIFFSetField(tif, dp->tdir_tag, data[0], data[1]);
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- break;
- case TIFF_SETGET_C0_UINT8:
- {
- uint8_t *data;
- assert(fip->field_readcount >= 1);
- assert(fip->field_passcount == 0);
- if (dp->tdir_count != (uint64_t)fip->field_readcount)
- {
- TIFFWarningExtR(tif, module,
- "incorrect count for field \"%s\", expected "
- "%d, got %" PRIu64,
- fip->field_name, (int)fip->field_readcount,
- dp->tdir_count);
- return (0);
- }
- else
- {
- err = TIFFReadDirEntryByteArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C0_SINT8:
- {
- int8_t *data;
- assert(fip->field_readcount >= 1);
- assert(fip->field_passcount == 0);
- if (dp->tdir_count != (uint64_t)fip->field_readcount)
- {
- TIFFWarningExtR(tif, module,
- "incorrect count for field \"%s\", expected "
- "%d, got %" PRIu64,
- fip->field_name, (int)fip->field_readcount,
- dp->tdir_count);
- return (0);
- }
- else
- {
- err = TIFFReadDirEntrySbyteArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C0_UINT16:
- {
- uint16_t *data;
- assert(fip->field_readcount >= 1);
- assert(fip->field_passcount == 0);
- if (dp->tdir_count != (uint64_t)fip->field_readcount)
- {
- TIFFWarningExtR(tif, module,
- "incorrect count for field \"%s\", expected "
- "%d, got %" PRIu64,
- fip->field_name, (int)fip->field_readcount,
- dp->tdir_count);
- return (0);
- }
- else
- {
- err = TIFFReadDirEntryShortArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C0_SINT16:
- {
- int16_t *data;
- assert(fip->field_readcount >= 1);
- assert(fip->field_passcount == 0);
- if (dp->tdir_count != (uint64_t)fip->field_readcount)
- {
- TIFFWarningExtR(tif, module,
- "incorrect count for field \"%s\", expected "
- "%d, got %" PRIu64,
- fip->field_name, (int)fip->field_readcount,
- dp->tdir_count);
- return (0);
- }
- else
- {
- err = TIFFReadDirEntrySshortArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C0_UINT32:
- {
- uint32_t *data;
- assert(fip->field_readcount >= 1);
- assert(fip->field_passcount == 0);
- if (dp->tdir_count != (uint64_t)fip->field_readcount)
- {
- TIFFWarningExtR(tif, module,
- "incorrect count for field \"%s\", expected "
- "%d, got %" PRIu64,
- fip->field_name, (int)fip->field_readcount,
- dp->tdir_count);
- return (0);
- }
- else
- {
- err = TIFFReadDirEntryLongArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C0_SINT32:
- {
- int32_t *data;
- assert(fip->field_readcount >= 1);
- assert(fip->field_passcount == 0);
- if (dp->tdir_count != (uint64_t)fip->field_readcount)
- {
- TIFFWarningExtR(tif, module,
- "incorrect count for field \"%s\", expected "
- "%d, got %" PRIu64,
- fip->field_name, (int)fip->field_readcount,
- dp->tdir_count);
- return (0);
- }
- else
- {
- err = TIFFReadDirEntrySlongArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C0_UINT64:
- {
- uint64_t *data;
- assert(fip->field_readcount >= 1);
- assert(fip->field_passcount == 0);
- if (dp->tdir_count != (uint64_t)fip->field_readcount)
- {
- TIFFWarningExtR(tif, module,
- "incorrect count for field \"%s\", expected "
- "%d, got %" PRIu64,
- fip->field_name, (int)fip->field_readcount,
- dp->tdir_count);
- return (0);
- }
- else
- {
- err = TIFFReadDirEntryLong8Array(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C0_SINT64:
- {
- int64_t *data;
- assert(fip->field_readcount >= 1);
- assert(fip->field_passcount == 0);
- if (dp->tdir_count != (uint64_t)fip->field_readcount)
- {
- TIFFWarningExtR(tif, module,
- "incorrect count for field \"%s\", expected "
- "%d, got %" PRIu64,
- fip->field_name, (int)fip->field_readcount,
- dp->tdir_count);
- return (0);
- }
- else
- {
- err = TIFFReadDirEntrySlong8Array(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C0_FLOAT:
- {
- float *data;
- assert(fip->field_readcount >= 1);
- assert(fip->field_passcount == 0);
- if (dp->tdir_count != (uint64_t)fip->field_readcount)
- {
- TIFFWarningExtR(tif, module,
- "incorrect count for field \"%s\", expected "
- "%d, got %" PRIu64,
- fip->field_name, (int)fip->field_readcount,
- dp->tdir_count);
- return (0);
- }
- else
- {
- err = TIFFReadDirEntryFloatArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- /*--: Rational2Double: Extend for Double Arrays and Rational-Arrays read
- * into Double-Arrays. */
- case TIFF_SETGET_C0_DOUBLE:
- {
- double *data;
- assert(fip->field_readcount >= 1);
- assert(fip->field_passcount == 0);
- if (dp->tdir_count != (uint64_t)fip->field_readcount)
- {
- TIFFWarningExtR(tif, module,
- "incorrect count for field \"%s\", expected "
- "%d, got %" PRIu64,
- fip->field_name, (int)fip->field_readcount,
- dp->tdir_count);
- return (0);
- }
- else
- {
- err = TIFFReadDirEntryDoubleArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C16_ASCII:
- {
- uint8_t *data;
- assert(fip->field_readcount == TIFF_VARIABLE);
- assert(fip->field_passcount == 1);
- if (dp->tdir_count > 0xFFFF)
- err = TIFFReadDirEntryErrCount;
- else
- {
- err = TIFFReadDirEntryByteArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- if (data != 0 && dp->tdir_count > 0 &&
- data[dp->tdir_count - 1] != '\0')
- {
- TIFFWarningExtR(tif, module,
- "ASCII value for ASCII array tag "
- "\"%s\" does not end in null "
- "byte. Forcing it to be null",
- fip->field_name);
- /* Enlarge buffer and add terminating null. */
- uint8_t *o =
- _TIFFmallocExt(tif, (uint32_t)dp->tdir_count + 1);
- if (o == NULL)
- {
- if (data != NULL)
- _TIFFfreeExt(tif, data);
- return (0);
- }
- if (dp->tdir_count > 0)
- {
- _TIFFmemcpy(o, data, (uint32_t)dp->tdir_count);
- }
- o[(uint32_t)dp->tdir_count] = 0;
- dp->tdir_count++; /* Increment for added null. */
- if (data != 0)
- _TIFFfreeExt(tif, data);
- data = o;
- }
- m = TIFFSetField(tif, dp->tdir_tag,
- (uint16_t)(dp->tdir_count), data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C16_UINT8:
- {
- uint8_t *data;
- assert(fip->field_readcount == TIFF_VARIABLE);
- assert(fip->field_passcount == 1);
- if (dp->tdir_count > 0xFFFF)
- err = TIFFReadDirEntryErrCount;
- else
- {
- err = TIFFReadDirEntryByteArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag,
- (uint16_t)(dp->tdir_count), data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C16_SINT8:
- {
- int8_t *data;
- assert(fip->field_readcount == TIFF_VARIABLE);
- assert(fip->field_passcount == 1);
- if (dp->tdir_count > 0xFFFF)
- err = TIFFReadDirEntryErrCount;
- else
- {
- err = TIFFReadDirEntrySbyteArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag,
- (uint16_t)(dp->tdir_count), data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C16_UINT16:
- {
- uint16_t *data;
- assert(fip->field_readcount == TIFF_VARIABLE);
- assert(fip->field_passcount == 1);
- if (dp->tdir_count > 0xFFFF)
- err = TIFFReadDirEntryErrCount;
- else
- {
- err = TIFFReadDirEntryShortArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag,
- (uint16_t)(dp->tdir_count), data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C16_SINT16:
- {
- int16_t *data;
- assert(fip->field_readcount == TIFF_VARIABLE);
- assert(fip->field_passcount == 1);
- if (dp->tdir_count > 0xFFFF)
- err = TIFFReadDirEntryErrCount;
- else
- {
- err = TIFFReadDirEntrySshortArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag,
- (uint16_t)(dp->tdir_count), data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C16_UINT32:
- {
- uint32_t *data;
- assert(fip->field_readcount == TIFF_VARIABLE);
- assert(fip->field_passcount == 1);
- if (dp->tdir_count > 0xFFFF)
- err = TIFFReadDirEntryErrCount;
- else
- {
- err = TIFFReadDirEntryLongArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag,
- (uint16_t)(dp->tdir_count), data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C16_SINT32:
- {
- int32_t *data;
- assert(fip->field_readcount == TIFF_VARIABLE);
- assert(fip->field_passcount == 1);
- if (dp->tdir_count > 0xFFFF)
- err = TIFFReadDirEntryErrCount;
- else
- {
- err = TIFFReadDirEntrySlongArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag,
- (uint16_t)(dp->tdir_count), data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C16_UINT64:
- {
- uint64_t *data;
- assert(fip->field_readcount == TIFF_VARIABLE);
- assert(fip->field_passcount == 1);
- if (dp->tdir_count > 0xFFFF)
- err = TIFFReadDirEntryErrCount;
- else
- {
- err = TIFFReadDirEntryLong8Array(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag,
- (uint16_t)(dp->tdir_count), data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C16_SINT64:
- {
- int64_t *data;
- assert(fip->field_readcount == TIFF_VARIABLE);
- assert(fip->field_passcount == 1);
- if (dp->tdir_count > 0xFFFF)
- err = TIFFReadDirEntryErrCount;
- else
- {
- err = TIFFReadDirEntrySlong8Array(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag,
- (uint16_t)(dp->tdir_count), data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C16_FLOAT:
- {
- float *data;
- assert(fip->field_readcount == TIFF_VARIABLE);
- assert(fip->field_passcount == 1);
- if (dp->tdir_count > 0xFFFF)
- err = TIFFReadDirEntryErrCount;
- else
- {
- err = TIFFReadDirEntryFloatArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag,
- (uint16_t)(dp->tdir_count), data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C16_DOUBLE:
- {
- double *data;
- assert(fip->field_readcount == TIFF_VARIABLE);
- assert(fip->field_passcount == 1);
- if (dp->tdir_count > 0xFFFF)
- err = TIFFReadDirEntryErrCount;
- else
- {
- err = TIFFReadDirEntryDoubleArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag,
- (uint16_t)(dp->tdir_count), data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C16_IFD8:
- {
- uint64_t *data;
- assert(fip->field_readcount == TIFF_VARIABLE);
- assert(fip->field_passcount == 1);
- if (dp->tdir_count > 0xFFFF)
- err = TIFFReadDirEntryErrCount;
- else
- {
- err = TIFFReadDirEntryIfd8Array(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag,
- (uint16_t)(dp->tdir_count), data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- }
- break;
- case TIFF_SETGET_C32_ASCII:
- {
- uint8_t *data;
- assert(fip->field_readcount == TIFF_VARIABLE2);
- assert(fip->field_passcount == 1);
- err = TIFFReadDirEntryByteArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- if (data != 0 && dp->tdir_count > 0 &&
- data[dp->tdir_count - 1] != '\0')
- {
- TIFFWarningExtR(
- tif, module,
- "ASCII value for ASCII array tag \"%s\" does not end "
- "in null byte. Forcing it to be null",
- fip->field_name);
- /* Enlarge buffer and add terminating null. */
- uint8_t *o =
- _TIFFmallocExt(tif, (uint32_t)dp->tdir_count + 1);
- if (o == NULL)
- {
- if (data != NULL)
- _TIFFfreeExt(tif, data);
- return (0);
- }
- if (dp->tdir_count > 0)
- {
- _TIFFmemcpy(o, data, (uint32_t)dp->tdir_count);
- }
- o[(uint32_t)dp->tdir_count] = 0;
- dp->tdir_count++; /* Increment for added null. */
- if (data != 0)
- _TIFFfreeExt(tif, data);
- data = o;
- }
- m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count),
- data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- break;
- case TIFF_SETGET_C32_UINT8:
- {
- uint8_t *data;
- uint32_t count = 0;
- assert(fip->field_readcount == TIFF_VARIABLE2);
- assert(fip->field_passcount == 1);
- if (fip->field_tag == TIFFTAG_RICHTIFFIPTC &&
- dp->tdir_type == TIFF_LONG)
- {
- /* Adobe's software (wrongly) writes RichTIFFIPTC tag with
- * data type LONG instead of UNDEFINED. Work around this
- * frequently found issue */
- void *origdata;
- err = TIFFReadDirEntryArray(tif, dp, &count, 4, &origdata);
- if ((err != TIFFReadDirEntryErrOk) || (origdata == 0))
- {
- data = NULL;
- }
- else
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong((uint32_t *)origdata, count);
- data = (uint8_t *)origdata;
- count = (uint32_t)(count * 4);
- }
- }
- else
- {
- err = TIFFReadDirEntryByteArray(tif, dp, &data);
- count = (uint32_t)(dp->tdir_count);
- }
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, count, data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- break;
- case TIFF_SETGET_C32_SINT8:
- {
- int8_t *data = NULL;
- assert(fip->field_readcount == TIFF_VARIABLE2);
- assert(fip->field_passcount == 1);
- err = TIFFReadDirEntrySbyteArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count),
- data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- break;
- case TIFF_SETGET_C32_UINT16:
- {
- uint16_t *data;
- assert(fip->field_readcount == TIFF_VARIABLE2);
- assert(fip->field_passcount == 1);
- err = TIFFReadDirEntryShortArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count),
- data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- break;
- case TIFF_SETGET_C32_SINT16:
- {
- int16_t *data = NULL;
- assert(fip->field_readcount == TIFF_VARIABLE2);
- assert(fip->field_passcount == 1);
- err = TIFFReadDirEntrySshortArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count),
- data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- break;
- case TIFF_SETGET_C32_UINT32:
- {
- uint32_t *data;
- assert(fip->field_readcount == TIFF_VARIABLE2);
- assert(fip->field_passcount == 1);
- err = TIFFReadDirEntryLongArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count),
- data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- break;
- case TIFF_SETGET_C32_SINT32:
- {
- int32_t *data = NULL;
- assert(fip->field_readcount == TIFF_VARIABLE2);
- assert(fip->field_passcount == 1);
- err = TIFFReadDirEntrySlongArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count),
- data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- break;
- case TIFF_SETGET_C32_UINT64:
- {
- uint64_t *data;
- assert(fip->field_readcount == TIFF_VARIABLE2);
- assert(fip->field_passcount == 1);
- err = TIFFReadDirEntryLong8Array(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count),
- data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- break;
- case TIFF_SETGET_C32_SINT64:
- {
- int64_t *data = NULL;
- assert(fip->field_readcount == TIFF_VARIABLE2);
- assert(fip->field_passcount == 1);
- err = TIFFReadDirEntrySlong8Array(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count),
- data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- break;
- case TIFF_SETGET_C32_FLOAT:
- {
- float *data;
- assert(fip->field_readcount == TIFF_VARIABLE2);
- assert(fip->field_passcount == 1);
- err = TIFFReadDirEntryFloatArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count),
- data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- break;
- case TIFF_SETGET_C32_DOUBLE:
- {
- double *data;
- assert(fip->field_readcount == TIFF_VARIABLE2);
- assert(fip->field_passcount == 1);
- err = TIFFReadDirEntryDoubleArray(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count),
- data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- break;
- case TIFF_SETGET_C32_IFD8:
- {
- uint64_t *data;
- assert(fip->field_readcount == TIFF_VARIABLE2);
- assert(fip->field_passcount == 1);
- err = TIFFReadDirEntryIfd8Array(tif, dp, &data);
- if (err == TIFFReadDirEntryErrOk)
- {
- if (!EvaluateIFDdatasizeReading(tif, dp))
- {
- if (data != 0)
- _TIFFfreeExt(tif, data);
- return 0;
- }
- int m;
- m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count),
- data);
- if (data != 0)
- _TIFFfreeExt(tif, data);
- if (!m)
- return (0);
- }
- }
- break;
- default:
- assert(0); /* we should never get here */
- break;
- }
- if (err != TIFFReadDirEntryErrOk)
- {
- TIFFReadDirEntryOutputErr(tif, err, module, fip->field_name, recover);
- return (0);
- }
- return (1);
- }
- /*
- * Fetch a set of offsets or lengths.
- * While this routine says "strips", in fact it's also used for tiles.
- */
- static int TIFFFetchStripThing(TIFF *tif, TIFFDirEntry *dir, uint32_t nstrips,
- uint64_t **lpp)
- {
- static const char module[] = "TIFFFetchStripThing";
- enum TIFFReadDirEntryErr err;
- uint64_t *data;
- err = TIFFReadDirEntryLong8ArrayWithLimit(tif, dir, &data, nstrips);
- if (err != TIFFReadDirEntryErrOk)
- {
- const TIFFField *fip = TIFFFieldWithTag(tif, dir->tdir_tag);
- TIFFReadDirEntryOutputErr(tif, err, module,
- fip ? fip->field_name : "unknown tagname", 0);
- return (0);
- }
- if (dir->tdir_count < (uint64_t)nstrips)
- {
- uint64_t *resizeddata;
- const TIFFField *fip = TIFFFieldWithTag(tif, dir->tdir_tag);
- const char *pszMax = getenv("LIBTIFF_STRILE_ARRAY_MAX_RESIZE_COUNT");
- uint32_t max_nstrips = 1000000;
- if (pszMax)
- max_nstrips = (uint32_t)atoi(pszMax);
- TIFFReadDirEntryOutputErr(tif, TIFFReadDirEntryErrCount, module,
- fip ? fip->field_name : "unknown tagname",
- (nstrips <= max_nstrips));
- if (nstrips > max_nstrips)
- {
- _TIFFfreeExt(tif, data);
- return (0);
- }
- const uint64_t allocsize = (uint64_t)nstrips * sizeof(uint64_t);
- if (allocsize > 100 * 1024 * 1024)
- {
- /* Before allocating a huge amount of memory for corrupted files,
- * check if size of requested memory is not greater than file size.
- */
- const uint64_t filesize = TIFFGetFileSize(tif);
- if (allocsize > filesize)
- {
- TIFFWarningExtR(
- tif, module,
- "Requested memory size for StripArray of %" PRIu64
- " is greater than filesize %" PRIu64
- ". Memory not allocated",
- allocsize, filesize);
- _TIFFfreeExt(tif, data);
- return (0);
- }
- }
- resizeddata = (uint64_t *)_TIFFCheckMalloc(
- tif, nstrips, sizeof(uint64_t), "for strip array");
- if (resizeddata == 0)
- {
- _TIFFfreeExt(tif, data);
- return (0);
- }
- if (dir->tdir_count)
- _TIFFmemcpy(resizeddata, data,
- (uint32_t)dir->tdir_count * sizeof(uint64_t));
- _TIFFmemset(resizeddata + (uint32_t)dir->tdir_count, 0,
- (nstrips - (uint32_t)dir->tdir_count) * sizeof(uint64_t));
- _TIFFfreeExt(tif, data);
- data = resizeddata;
- }
- *lpp = data;
- return (1);
- }
- /*
- * Fetch and set the SubjectDistance EXIF tag.
- */
- static int TIFFFetchSubjectDistance(TIFF *tif, TIFFDirEntry *dir)
- {
- static const char module[] = "TIFFFetchSubjectDistance";
- enum TIFFReadDirEntryErr err;
- UInt64Aligned_t m;
- m.l = 0;
- assert(sizeof(double) == 8);
- assert(sizeof(uint64_t) == 8);
- assert(sizeof(uint32_t) == 4);
- if (dir->tdir_count != 1)
- err = TIFFReadDirEntryErrCount;
- else if (dir->tdir_type != TIFF_RATIONAL)
- err = TIFFReadDirEntryErrType;
- else
- {
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- uint32_t offset;
- offset = *(uint32_t *)(&dir->tdir_offset);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&offset);
- err = TIFFReadDirEntryData(tif, offset, 8, m.i);
- }
- else
- {
- m.l = dir->tdir_offset.toff_long8;
- err = TIFFReadDirEntryErrOk;
- }
- }
- if (err == TIFFReadDirEntryErrOk)
- {
- double n;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong(m.i, 2);
- if (m.i[0] == 0)
- n = 0.0;
- else if (m.i[0] == 0xFFFFFFFF || m.i[1] == 0)
- /*
- * XXX: Numerator 0xFFFFFFFF means that we have infinite
- * distance. Indicate that with a negative floating point
- * SubjectDistance value.
- */
- n = -1.0;
- else
- n = (double)m.i[0] / (double)m.i[1];
- return (TIFFSetField(tif, dir->tdir_tag, n));
- }
- else
- {
- TIFFReadDirEntryOutputErr(tif, err, module, "SubjectDistance", TRUE);
- return (0);
- }
- }
- static void allocChoppedUpStripArrays(TIFF *tif, uint32_t nstrips,
- uint64_t stripbytes,
- uint32_t rowsperstrip)
- {
- TIFFDirectory *td = &tif->tif_dir;
- uint64_t bytecount;
- uint64_t offset;
- uint64_t last_offset;
- uint64_t last_bytecount;
- uint32_t i;
- uint64_t *newcounts;
- uint64_t *newoffsets;
- offset = TIFFGetStrileOffset(tif, 0);
- last_offset = TIFFGetStrileOffset(tif, td->td_nstrips - 1);
- last_bytecount = TIFFGetStrileByteCount(tif, td->td_nstrips - 1);
- if (last_offset > UINT64_MAX - last_bytecount ||
- last_offset + last_bytecount < offset)
- {
- return;
- }
- bytecount = last_offset + last_bytecount - offset;
- /* Before allocating a huge amount of memory for corrupted files, check if
- * size of StripByteCount and StripOffset tags is not greater than
- * file size.
- */
- const uint64_t allocsize = (uint64_t)nstrips * sizeof(uint64_t) * 2;
- if (allocsize > 100 * 1024 * 1024)
- {
- const uint64_t filesize = TIFFGetFileSize(tif);
- if (allocsize > filesize)
- {
- TIFFWarningExtR(tif, "allocChoppedUpStripArrays",
- "Requested memory size for StripByteCount and "
- "StripOffsets %" PRIu64
- " is greater than filesize %" PRIu64
- ". Memory not allocated",
- allocsize, filesize);
- return;
- }
- }
- newcounts =
- (uint64_t *)_TIFFCheckMalloc(tif, nstrips, sizeof(uint64_t),
- "for chopped \"StripByteCounts\" array");
- newoffsets = (uint64_t *)_TIFFCheckMalloc(
- tif, nstrips, sizeof(uint64_t), "for chopped \"StripOffsets\" array");
- if (newcounts == NULL || newoffsets == NULL)
- {
- /*
- * Unable to allocate new strip information, give up and use
- * the original one strip information.
- */
- if (newcounts != NULL)
- _TIFFfreeExt(tif, newcounts);
- if (newoffsets != NULL)
- _TIFFfreeExt(tif, newoffsets);
- return;
- }
- /*
- * Fill the strip information arrays with new bytecounts and offsets
- * that reflect the broken-up format.
- */
- for (i = 0; i < nstrips; i++)
- {
- if (stripbytes > bytecount)
- stripbytes = bytecount;
- newcounts[i] = stripbytes;
- newoffsets[i] = stripbytes ? offset : 0;
- offset += stripbytes;
- bytecount -= stripbytes;
- }
- /*
- * Replace old single strip info with multi-strip info.
- */
- td->td_stripsperimage = td->td_nstrips = nstrips;
- TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
- _TIFFfreeExt(tif, td->td_stripbytecount_p);
- _TIFFfreeExt(tif, td->td_stripoffset_p);
- td->td_stripbytecount_p = newcounts;
- td->td_stripoffset_p = newoffsets;
- #ifdef STRIPBYTECOUNTSORTED_UNUSED
- td->td_stripbytecountsorted = 1;
- #endif
- tif->tif_flags |= TIFF_CHOPPEDUPARRAYS;
- }
- /*
- * Replace a single strip (tile) of uncompressed data by multiple strips
- * (tiles), each approximately STRIP_SIZE_DEFAULT bytes. This is useful for
- * dealing with large images or for dealing with machines with a limited
- * amount memory.
- */
- static void ChopUpSingleUncompressedStrip(TIFF *tif)
- {
- register TIFFDirectory *td = &tif->tif_dir;
- uint64_t bytecount;
- uint64_t offset;
- uint32_t rowblock;
- uint64_t rowblockbytes;
- uint64_t stripbytes;
- uint32_t nstrips;
- uint32_t rowsperstrip;
- bytecount = TIFFGetStrileByteCount(tif, 0);
- /* On a newly created file, just re-opened to be filled, we */
- /* don't want strip chop to trigger as it is going to cause issues */
- /* later ( StripOffsets and StripByteCounts improperly filled) . */
- if (bytecount == 0 && tif->tif_mode != O_RDONLY)
- return;
- offset = TIFFGetStrileByteCount(tif, 0);
- assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
- if ((td->td_photometric == PHOTOMETRIC_YCBCR) && (!isUpSampled(tif)))
- rowblock = td->td_ycbcrsubsampling[1];
- else
- rowblock = 1;
- rowblockbytes = TIFFVTileSize64(tif, rowblock);
- /*
- * Make the rows hold at least one scanline, but fill specified amount
- * of data if possible.
- */
- if (rowblockbytes > STRIP_SIZE_DEFAULT)
- {
- stripbytes = rowblockbytes;
- rowsperstrip = rowblock;
- }
- else if (rowblockbytes > 0)
- {
- uint32_t rowblocksperstrip;
- rowblocksperstrip = (uint32_t)(STRIP_SIZE_DEFAULT / rowblockbytes);
- rowsperstrip = rowblocksperstrip * rowblock;
- stripbytes = rowblocksperstrip * rowblockbytes;
- }
- else
- return;
- /*
- * never increase the number of rows per strip
- */
- if (rowsperstrip >= td->td_rowsperstrip || rowsperstrip == 0)
- return;
- nstrips = TIFFhowmany_32(td->td_imagelength, rowsperstrip);
- if (nstrips == 0)
- return;
- /* If we are going to allocate a lot of memory, make sure that the */
- /* file is as big as needed */
- if (tif->tif_mode == O_RDONLY && nstrips > 1000000 &&
- (offset >= TIFFGetFileSize(tif) ||
- stripbytes > (TIFFGetFileSize(tif) - offset) / (nstrips - 1)))
- {
- return;
- }
- allocChoppedUpStripArrays(tif, nstrips, stripbytes, rowsperstrip);
- }
- /*
- * Replace a file with contiguous strips > 2 GB of uncompressed data by
- * multiple smaller strips. This is useful for
- * dealing with large images or for dealing with machines with a limited
- * amount memory.
- */
- static void TryChopUpUncompressedBigTiff(TIFF *tif)
- {
- TIFFDirectory *td = &tif->tif_dir;
- uint32_t rowblock;
- uint64_t rowblockbytes;
- uint32_t i;
- uint64_t stripsize;
- uint32_t rowblocksperstrip;
- uint32_t rowsperstrip;
- uint64_t stripbytes;
- uint32_t nstrips;
- stripsize = TIFFStripSize64(tif);
- assert(tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG);
- assert(tif->tif_dir.td_compression == COMPRESSION_NONE);
- assert((tif->tif_flags & (TIFF_STRIPCHOP | TIFF_ISTILED)) ==
- TIFF_STRIPCHOP);
- assert(stripsize > 0x7FFFFFFFUL);
- /* On a newly created file, just re-opened to be filled, we */
- /* don't want strip chop to trigger as it is going to cause issues */
- /* later ( StripOffsets and StripByteCounts improperly filled) . */
- if (TIFFGetStrileByteCount(tif, 0) == 0 && tif->tif_mode != O_RDONLY)
- return;
- if ((td->td_photometric == PHOTOMETRIC_YCBCR) && (!isUpSampled(tif)))
- rowblock = td->td_ycbcrsubsampling[1];
- else
- rowblock = 1;
- rowblockbytes = TIFFVStripSize64(tif, rowblock);
- if (rowblockbytes == 0 || rowblockbytes > 0x7FFFFFFFUL)
- {
- /* In case of file with gigantic width */
- return;
- }
- /* Check that the strips are contiguous and of the expected size */
- for (i = 0; i < td->td_nstrips; i++)
- {
- if (i == td->td_nstrips - 1)
- {
- if (TIFFGetStrileByteCount(tif, i) <
- TIFFVStripSize64(tif,
- td->td_imagelength - i * td->td_rowsperstrip))
- {
- return;
- }
- }
- else
- {
- if (TIFFGetStrileByteCount(tif, i) != stripsize)
- {
- return;
- }
- if (i > 0 && TIFFGetStrileOffset(tif, i) !=
- TIFFGetStrileOffset(tif, i - 1) +
- TIFFGetStrileByteCount(tif, i - 1))
- {
- return;
- }
- }
- }
- /* Aim for 512 MB strips (that will still be manageable by 32 bit builds */
- rowblocksperstrip = (uint32_t)(512 * 1024 * 1024 / rowblockbytes);
- if (rowblocksperstrip == 0)
- rowblocksperstrip = 1;
- rowsperstrip = rowblocksperstrip * rowblock;
- stripbytes = rowblocksperstrip * rowblockbytes;
- assert(stripbytes <= 0x7FFFFFFFUL);
- if (rowsperstrip == 0)
- return;
- nstrips = TIFFhowmany_32(td->td_imagelength, rowsperstrip);
- if (nstrips == 0)
- return;
- /* If we are going to allocate a lot of memory, make sure that the */
- /* file is as big as needed */
- if (tif->tif_mode == O_RDONLY && nstrips > 1000000)
- {
- uint64_t last_offset = TIFFGetStrileOffset(tif, td->td_nstrips - 1);
- uint64_t filesize = TIFFGetFileSize(tif);
- uint64_t last_bytecount =
- TIFFGetStrileByteCount(tif, td->td_nstrips - 1);
- if (last_offset > filesize || last_bytecount > filesize - last_offset)
- {
- return;
- }
- }
- allocChoppedUpStripArrays(tif, nstrips, stripbytes, rowsperstrip);
- }
- TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
- static uint64_t _TIFFUnsanitizedAddUInt64AndInt(uint64_t a, int b)
- {
- return a + b;
- }
- /* Read the value of [Strip|Tile]Offset or [Strip|Tile]ByteCount around
- * strip/tile of number strile. Also fetch the neighbouring values using a
- * 4096 byte page size.
- */
- static int _TIFFPartialReadStripArray(TIFF *tif, TIFFDirEntry *dirent,
- int strile, uint64_t *panVals)
- {
- static const char module[] = "_TIFFPartialReadStripArray";
- #define IO_CACHE_PAGE_SIZE 4096
- size_t sizeofval;
- const int bSwab = (tif->tif_flags & TIFF_SWAB) != 0;
- int sizeofvalint;
- uint64_t nBaseOffset;
- uint64_t nOffset;
- uint64_t nOffsetStartPage;
- uint64_t nOffsetEndPage;
- tmsize_t nToRead;
- tmsize_t nRead;
- uint64_t nLastStripOffset;
- int iStartBefore;
- int i;
- const uint32_t arraySize = tif->tif_dir.td_stripoffsetbyteallocsize;
- unsigned char buffer[2 * IO_CACHE_PAGE_SIZE];
- assert(dirent->tdir_count > 4);
- if (dirent->tdir_type == TIFF_SHORT)
- {
- sizeofval = sizeof(uint16_t);
- }
- else if (dirent->tdir_type == TIFF_LONG)
- {
- sizeofval = sizeof(uint32_t);
- }
- else if (dirent->tdir_type == TIFF_LONG8)
- {
- sizeofval = sizeof(uint64_t);
- }
- else if (dirent->tdir_type == TIFF_SLONG8)
- {
- /* Non conformant but used by some images as in */
- /* https://github.com/OSGeo/gdal/issues/2165 */
- sizeofval = sizeof(int64_t);
- }
- else
- {
- TIFFErrorExtR(tif, module,
- "Invalid type for [Strip|Tile][Offset/ByteCount] tag");
- panVals[strile] = 0;
- return 0;
- }
- sizeofvalint = (int)(sizeofval);
- if (tif->tif_flags & TIFF_BIGTIFF)
- {
- uint64_t offset = dirent->tdir_offset.toff_long8;
- if (bSwab)
- TIFFSwabLong8(&offset);
- nBaseOffset = offset;
- }
- else
- {
- uint32_t offset = dirent->tdir_offset.toff_long;
- if (bSwab)
- TIFFSwabLong(&offset);
- nBaseOffset = offset;
- }
- /* To avoid later unsigned integer overflows */
- if (nBaseOffset > (uint64_t)INT64_MAX)
- {
- TIFFErrorExtR(tif, module, "Cannot read offset/size for strile %d",
- strile);
- panVals[strile] = 0;
- return 0;
- }
- nOffset = nBaseOffset + sizeofval * strile;
- nOffsetStartPage = (nOffset / IO_CACHE_PAGE_SIZE) * IO_CACHE_PAGE_SIZE;
- nOffsetEndPage = nOffsetStartPage + IO_CACHE_PAGE_SIZE;
- if (nOffset + sizeofval > nOffsetEndPage)
- nOffsetEndPage += IO_CACHE_PAGE_SIZE;
- #undef IO_CACHE_PAGE_SIZE
- nLastStripOffset = nBaseOffset + arraySize * sizeofval;
- if (nLastStripOffset < nOffsetEndPage)
- nOffsetEndPage = nLastStripOffset;
- if (nOffsetStartPage >= nOffsetEndPage)
- {
- TIFFErrorExtR(tif, module, "Cannot read offset/size for strile %d",
- strile);
- panVals[strile] = 0;
- return 0;
- }
- if (!SeekOK(tif, nOffsetStartPage))
- {
- panVals[strile] = 0;
- return 0;
- }
- nToRead = (tmsize_t)(nOffsetEndPage - nOffsetStartPage);
- nRead = TIFFReadFile(tif, buffer, nToRead);
- if (nRead < nToRead)
- {
- TIFFErrorExtR(tif, module,
- "Cannot read offset/size for strile around ~%d", strile);
- return 0;
- }
- iStartBefore = -(int)((nOffset - nOffsetStartPage) / sizeofval);
- if (strile + iStartBefore < 0)
- iStartBefore = -strile;
- for (i = iStartBefore;
- (uint32_t)(strile + i) < arraySize &&
- _TIFFUnsanitizedAddUInt64AndInt(nOffset, (i + 1) * sizeofvalint) <=
- nOffsetEndPage;
- ++i)
- {
- if (dirent->tdir_type == TIFF_SHORT)
- {
- uint16_t val;
- memcpy(&val,
- buffer + (nOffset - nOffsetStartPage) + i * sizeofvalint,
- sizeof(val));
- if (bSwab)
- TIFFSwabShort(&val);
- panVals[strile + i] = val;
- }
- else if (dirent->tdir_type == TIFF_LONG)
- {
- uint32_t val;
- memcpy(&val,
- buffer + (nOffset - nOffsetStartPage) + i * sizeofvalint,
- sizeof(val));
- if (bSwab)
- TIFFSwabLong(&val);
- panVals[strile + i] = val;
- }
- else if (dirent->tdir_type == TIFF_LONG8)
- {
- uint64_t val;
- memcpy(&val,
- buffer + (nOffset - nOffsetStartPage) + i * sizeofvalint,
- sizeof(val));
- if (bSwab)
- TIFFSwabLong8(&val);
- panVals[strile + i] = val;
- }
- else /* if( dirent->tdir_type == TIFF_SLONG8 ) */
- {
- /* Non conformant data type */
- int64_t val;
- memcpy(&val,
- buffer + (nOffset - nOffsetStartPage) + i * sizeofvalint,
- sizeof(val));
- if (bSwab)
- TIFFSwabLong8((uint64_t *)&val);
- panVals[strile + i] = (uint64_t)val;
- }
- }
- return 1;
- }
- static int _TIFFFetchStrileValue(TIFF *tif, uint32_t strile,
- TIFFDirEntry *dirent, uint64_t **parray)
- {
- static const char module[] = "_TIFFFetchStrileValue";
- TIFFDirectory *td = &tif->tif_dir;
- if (strile >= dirent->tdir_count)
- {
- return 0;
- }
- if (strile >= td->td_stripoffsetbyteallocsize)
- {
- uint32_t nStripArrayAllocBefore = td->td_stripoffsetbyteallocsize;
- uint32_t nStripArrayAllocNew;
- uint64_t nArraySize64;
- size_t nArraySize;
- uint64_t *offsetArray;
- uint64_t *bytecountArray;
- if (strile > 1000000)
- {
- uint64_t filesize = TIFFGetFileSize(tif);
- /* Avoid excessive memory allocation attempt */
- /* For such a big blockid we need at least a TIFF_LONG per strile */
- /* for the offset array. */
- if (strile > filesize / sizeof(uint32_t))
- {
- TIFFErrorExtR(tif, module, "File too short");
- return 0;
- }
- }
- if (td->td_stripoffsetbyteallocsize == 0 &&
- td->td_nstrips < 1024 * 1024)
- {
- nStripArrayAllocNew = td->td_nstrips;
- }
- else
- {
- #define TIFF_MAX(a, b) (((a) > (b)) ? (a) : (b))
- #define TIFF_MIN(a, b) (((a) < (b)) ? (a) : (b))
- nStripArrayAllocNew = TIFF_MAX(strile + 1, 1024U * 512U);
- if (nStripArrayAllocNew < 0xFFFFFFFFU / 2)
- nStripArrayAllocNew *= 2;
- nStripArrayAllocNew = TIFF_MIN(nStripArrayAllocNew, td->td_nstrips);
- }
- assert(strile < nStripArrayAllocNew);
- nArraySize64 = (uint64_t)sizeof(uint64_t) * nStripArrayAllocNew;
- nArraySize = (size_t)(nArraySize64);
- #if SIZEOF_SIZE_T == 4
- if (nArraySize != nArraySize64)
- {
- TIFFErrorExtR(tif, module,
- "Cannot allocate strip offset and bytecount arrays");
- return 0;
- }
- #endif
- offsetArray = (uint64_t *)(_TIFFreallocExt(tif, td->td_stripoffset_p,
- nArraySize));
- bytecountArray = (uint64_t *)(_TIFFreallocExt(
- tif, td->td_stripbytecount_p, nArraySize));
- if (offsetArray)
- td->td_stripoffset_p = offsetArray;
- if (bytecountArray)
- td->td_stripbytecount_p = bytecountArray;
- if (offsetArray && bytecountArray)
- {
- td->td_stripoffsetbyteallocsize = nStripArrayAllocNew;
- /* Initialize new entries to ~0 / -1 */
- /* coverity[overrun-buffer-arg] */
- memset(td->td_stripoffset_p + nStripArrayAllocBefore, 0xFF,
- (td->td_stripoffsetbyteallocsize - nStripArrayAllocBefore) *
- sizeof(uint64_t));
- /* coverity[overrun-buffer-arg] */
- memset(td->td_stripbytecount_p + nStripArrayAllocBefore, 0xFF,
- (td->td_stripoffsetbyteallocsize - nStripArrayAllocBefore) *
- sizeof(uint64_t));
- }
- else
- {
- TIFFErrorExtR(tif, module,
- "Cannot allocate strip offset and bytecount arrays");
- _TIFFfreeExt(tif, td->td_stripoffset_p);
- td->td_stripoffset_p = NULL;
- _TIFFfreeExt(tif, td->td_stripbytecount_p);
- td->td_stripbytecount_p = NULL;
- td->td_stripoffsetbyteallocsize = 0;
- }
- }
- if (*parray == NULL || strile >= td->td_stripoffsetbyteallocsize)
- return 0;
- if (~((*parray)[strile]) == 0)
- {
- if (!_TIFFPartialReadStripArray(tif, dirent, strile, *parray))
- {
- (*parray)[strile] = 0;
- return 0;
- }
- }
- return 1;
- }
- static uint64_t _TIFFGetStrileOffsetOrByteCountValue(TIFF *tif, uint32_t strile,
- TIFFDirEntry *dirent,
- uint64_t **parray,
- int *pbErr)
- {
- TIFFDirectory *td = &tif->tif_dir;
- if (pbErr)
- *pbErr = 0;
- if ((tif->tif_flags & TIFF_DEFERSTRILELOAD) &&
- !(tif->tif_flags & TIFF_CHOPPEDUPARRAYS))
- {
- if (!(tif->tif_flags & TIFF_LAZYSTRILELOAD) ||
- /* If the values may fit in the toff_long/toff_long8 member */
- /* then use _TIFFFillStriles to simplify _TIFFFetchStrileValue */
- dirent->tdir_count <= 4)
- {
- if (!_TIFFFillStriles(tif))
- {
- if (pbErr)
- *pbErr = 1;
- /* Do not return, as we want this function to always */
- /* return the same value if called several times with */
- /* the same arguments */
- }
- }
- else
- {
- if (!_TIFFFetchStrileValue(tif, strile, dirent, parray))
- {
- if (pbErr)
- *pbErr = 1;
- return 0;
- }
- }
- }
- if (*parray == NULL || strile >= td->td_nstrips)
- {
- if (pbErr)
- *pbErr = 1;
- return 0;
- }
- return (*parray)[strile];
- }
- /* Return the value of the TileOffsets/StripOffsets array for the specified
- * tile/strile */
- uint64_t TIFFGetStrileOffset(TIFF *tif, uint32_t strile)
- {
- return TIFFGetStrileOffsetWithErr(tif, strile, NULL);
- }
- /* Return the value of the TileOffsets/StripOffsets array for the specified
- * tile/strile */
- uint64_t TIFFGetStrileOffsetWithErr(TIFF *tif, uint32_t strile, int *pbErr)
- {
- TIFFDirectory *td = &tif->tif_dir;
- return _TIFFGetStrileOffsetOrByteCountValue(tif, strile,
- &(td->td_stripoffset_entry),
- &(td->td_stripoffset_p), pbErr);
- }
- /* Return the value of the TileByteCounts/StripByteCounts array for the
- * specified tile/strile */
- uint64_t TIFFGetStrileByteCount(TIFF *tif, uint32_t strile)
- {
- return TIFFGetStrileByteCountWithErr(tif, strile, NULL);
- }
- /* Return the value of the TileByteCounts/StripByteCounts array for the
- * specified tile/strile */
- uint64_t TIFFGetStrileByteCountWithErr(TIFF *tif, uint32_t strile, int *pbErr)
- {
- TIFFDirectory *td = &tif->tif_dir;
- return _TIFFGetStrileOffsetOrByteCountValue(
- tif, strile, &(td->td_stripbytecount_entry), &(td->td_stripbytecount_p),
- pbErr);
- }
- int _TIFFFillStriles(TIFF *tif) { return _TIFFFillStrilesInternal(tif, 1); }
- static int _TIFFFillStrilesInternal(TIFF *tif, int loadStripByteCount)
- {
- register TIFFDirectory *td = &tif->tif_dir;
- int return_value = 1;
- /* Do not do anything if TIFF_DEFERSTRILELOAD is not set */
- if (!(tif->tif_flags & TIFF_DEFERSTRILELOAD) ||
- (tif->tif_flags & TIFF_CHOPPEDUPARRAYS) != 0)
- return 1;
- if (tif->tif_flags & TIFF_LAZYSTRILELOAD)
- {
- /* In case of lazy loading, reload completely the arrays */
- _TIFFfreeExt(tif, td->td_stripoffset_p);
- _TIFFfreeExt(tif, td->td_stripbytecount_p);
- td->td_stripoffset_p = NULL;
- td->td_stripbytecount_p = NULL;
- td->td_stripoffsetbyteallocsize = 0;
- tif->tif_flags &= ~TIFF_LAZYSTRILELOAD;
- }
- /* If stripoffset array is already loaded, exit with success */
- if (td->td_stripoffset_p != NULL)
- return 1;
- /* If tdir_count was canceled, then we already got there, but in error */
- if (td->td_stripoffset_entry.tdir_count == 0)
- return 0;
- if (!TIFFFetchStripThing(tif, &(td->td_stripoffset_entry), td->td_nstrips,
- &td->td_stripoffset_p))
- {
- return_value = 0;
- }
- if (loadStripByteCount &&
- !TIFFFetchStripThing(tif, &(td->td_stripbytecount_entry),
- td->td_nstrips, &td->td_stripbytecount_p))
- {
- return_value = 0;
- }
- _TIFFmemset(&(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry));
- _TIFFmemset(&(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry));
- #ifdef STRIPBYTECOUNTSORTED_UNUSED
- if (tif->tif_dir.td_nstrips > 1 && return_value == 1)
- {
- uint32_t strip;
- tif->tif_dir.td_stripbytecountsorted = 1;
- for (strip = 1; strip < tif->tif_dir.td_nstrips; strip++)
- {
- if (tif->tif_dir.td_stripoffset_p[strip - 1] >
- tif->tif_dir.td_stripoffset_p[strip])
- {
- tif->tif_dir.td_stripbytecountsorted = 0;
- break;
- }
- }
- }
- #endif
- return return_value;
- }
|