1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894 |
- /*
- * 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
- 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);
- #if defined(__WIN32__) && (_MSC_VER < 1500)
- /*
- * XXX: MSVC 6.0 does not support conversion
- * of 64-bit integers into floating point
- * values.
- */
- *value = _TIFFUInt64ToFloat(m);
- #else
- *value = (float)m;
- #endif
- 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);
- #if defined(__WIN32__) && (_MSC_VER < 1500)
- /*
- * XXX: MSVC 6.0 does not support conversion
- * of 64-bit integers into floating point
- * values.
- */
- *value = _TIFFUInt64ToDouble(m);
- #else
- *value = (double)m;
- #endif
- 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 (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);
- TIFFCvtIEEEDoubleToNative(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);
- #if defined(__WIN32__) && (_MSC_VER < 1500)
- /*
- * XXX: MSVC 6.0 does not support
- * conversion of 64-bit integers into
- * floating point values.
- */
- *mb++ = _TIFFUInt64ToFloat(*ma++);
- #else
- *mb++ = (float)(*ma++);
- #endif
- }
- }
- 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);
- #if defined(__WIN32__) && (_MSC_VER < 1500)
- /*
- * XXX: MSVC 6.0 does not support
- * conversion of 64-bit integers into
- * floating point values.
- */
- *mb++ = _TIFFUInt64ToDouble(*ma++);
- #else
- *mb++ = (double)(*ma++);
- #endif
- }
- }
- 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;
- }
- /*
- * 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++;
- (*tif->tif_cleanup)(tif); /* cleanup any previous compression state */
- 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);
- /*
- * 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)
- {
- 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 */
- if (!_TIFFMergeFields(
- tif,
- _TIFFCreateAnonField(tif, dp->tdir_tag,
- (TIFFDataType)dp->tdir_type),
- 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))
- {
- TIFFWarningExtR(tif, module, "TIFF directory is missing required ImageLength field");
- }
- /*
- * 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 (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 (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));
- 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));
- 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 (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;
- }
- } /* -- if (!dp->tdir_ignore) */
- } /* -- for-loop -- */
- /*
- * 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)
- {
- TIFFWarningExtR(tif, module, "Cannot handle zero scanline size");
- }
- if (isTiled(tif))
- {
- tif->tif_tilesize = TIFFTileSize(tif);
- if (!tif->tif_tilesize)
- {
- TIFFWarningExtR(tif, module, "Cannot handle zero tile size");
- }
- }
- else
- {
- if (!TIFFStripSize(tif))
- {
- TIFFWarningExt(tif, module, "Cannot handle zero strip size");
- }
- }
- return (1);
- bad:
- if (dir)
- _TIFFfreeExt(tif, dir);
- return (0);
- }
- 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;
- (*tif->tif_cleanup)(tif); /* cleanup any previous compression state */
- _TIFFSetupFields(tif, infoarray);
- dircount = TIFFFetchDirectory(tif, diroff, &dir, NULL);
- if (!dircount)
- {
- TIFFWarningExtR(tif, module,
- "Failed to read custom directory at offset %" PRIu64,
- diroff);
- return 0;
- }
- TIFFFreeDirectory(tif);
- _TIFFmemset(&tif->tif_dir, 0, sizeof(TIFFDirectory));
- TIFFReadDirectoryCheckOrder(tif, dir, dircount);
- for (di = 0, dp = dir; di < dircount; di++, dp++)
- {
- TIFFReadDirectoryFindFieldInfo(tif, dp->tdir_tag, &fii);
- if (fii == FAILED_FII)
- {
- TIFFWarningExtR(tif, module,
- "Unknown field with tag %" PRIu16 " (0x%" PRIx16
- ") encountered",
- dp->tdir_tag, dp->tdir_tag);
- if (!_TIFFMergeFields(
- tif,
- _TIFFCreateAnonField(tif, dp->tdir_tag,
- (TIFFDataType)dp->tdir_type),
- 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
- {
- /* 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) */
- }
- }
- /* 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)
- {
- const TIFFFieldArray *exifFieldArray;
- exifFieldArray = _TIFFGetExifFields();
- return TIFFReadCustomDirectory(tif, diroff, exifFieldArray);
- }
- /*
- *--: EXIF-GPS custom directory reading as another special case of custom IFD.
- */
- int TIFFReadGPSDirectory(TIFF *tif, toff_t diroff)
- {
- const TIFFFieldArray *gpsFieldArray;
- gpsFieldArray = _TIFFGetGpsFields();
- return TIFFReadCustomDirectory(tif, diroff, gpsFieldArray);
- }
- 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;
- 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;
- uint64_t filesize;
- uint16_t n;
- filesize = TIFFGetFileSize(tif);
- 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 < 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";
- TIFFWarningExtR(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)
- {
- TIFFWarningExtR(tif, module,
- "Sanity check on directory count failed, zero tag "
- "directories not supported");
- 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);
- }
- }
- }
- 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_field_type !=
- TIFF_SETGET_OTHER); /* if so, we shouldn't arrive here but deal with
- this in specialized code */
- assert(fip->set_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_field_type)
- {
- case TIFF_SETGET_UNDEFINED:
- TIFFErrorExtR(
- tif, "TIFFFetchNormalTag",
- "Defined set_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 (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)
- {
- uint8_t *o;
- TIFFWarningExtR(
- tif, module,
- "ASCII value for tag \"%s\" does not end in null byte",
- 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);
- 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 (!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 (!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 (!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 (!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 (!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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- int m;
- if (data != 0 && dp->tdir_count > 0 &&
- data[dp->tdir_count - 1] != '\0')
- {
- TIFFWarningExtR(
- tif, module,
- "ASCII value for tag \"%s\" does not end in null "
- "byte. Forcing it to be null",
- fip->field_name);
- data[dp->tdir_count - 1] = '\0';
- }
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- int m;
- if (data != 0 && dp->tdir_count > 0 &&
- data[dp->tdir_count - 1] != '\0')
- {
- TIFFWarningExtR(tif, module,
- "ASCII value for tag \"%s\" does not end "
- "in null byte. Forcing it to be null",
- fip->field_name);
- data[dp->tdir_count - 1] = '\0';
- }
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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);
- }
- 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;
- 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)
- 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);
- 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;
- }
|