From 0a92b2b40c7335b1859160ac2f26179eefb202be Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Wed, 27 Nov 2024 14:50:17 +0100 Subject: [PATCH] OpenFileGDB: be robust to unusual .gdbindexes files with weid/corrupted/not-understood entries Fixes #11295 --- .../a00000001.gdbtable | Bin 0 -> 370 bytes .../a00000001.gdbtablx | Bin 0 -> 4128 bytes .../a00000002.gdbtable | Bin 0 -> 2094 bytes .../a00000002.gdbtablx | Bin 0 -> 4128 bytes .../a00000003.gdbtable | Bin 0 -> 564 bytes .../a00000003.gdbtablx | Bin 0 -> 4128 bytes .../a00000004.gdbtable | Bin 0 -> 3170 bytes .../a00000004.gdbtablx | Bin 0 -> 4128 bytes .../a00000005.gdbtable | Bin 0 -> 1744 bytes .../a00000005.gdbtablx | Bin 0 -> 4128 bytes .../a00000006.gdbtable | Bin 0 -> 302 bytes .../a00000006.gdbtablx | Bin 0 -> 4128 bytes .../a00000007.gdbtable | Bin 0 -> 2302 bytes .../a00000007.gdbtablx | Bin 0 -> 4128 bytes .../a00000009.gdbindexes | Bin 0 -> 460 bytes .../a00000009.gdbtable | Bin 0 -> 134 bytes .../a00000009.gdbtablx | Bin 0 -> 5152 bytes .../data/filegdb/corrupted_gdbindexes.gdb/gdb | Bin 0 -> 8 bytes .../corrupted_gdbindexes.gdb/timestamps | 1 + autotest/ogr/ogr_openfilegdb.py | 16 +++++ ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp | 55 ++++++++++++++++-- 21 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000001.gdbtable create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000001.gdbtablx create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000002.gdbtable create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000002.gdbtablx create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000003.gdbtable create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000003.gdbtablx create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000004.gdbtable create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000004.gdbtablx create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000005.gdbtable create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000005.gdbtablx create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000006.gdbtable create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000006.gdbtablx create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000007.gdbtable create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000007.gdbtablx create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000009.gdbindexes create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000009.gdbtable create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000009.gdbtablx create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/gdb create mode 100644 autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/timestamps diff --git a/autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000001.gdbtable b/autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000001.gdbtable new file mode 100644 index 0000000000000000000000000000000000000000..b8df547eda91f04747fbd8a4fa2759405e1f2342 GIT binary patch literal 370 zcmZvVPfEi;7{x!+QE0)6S_NIG7iejaE?gQzOR>0!-Iqz{OB|RcA(@J~jTi6=9>pto z1>dB`l>?6%e(%q8h^Pw%&_2|ja&Px~`~}yzXW{+g=62-!qp{-Gp+6Z&o)x zL0W0@6p)Ufo^!%rxy`UgG;p{H7t(5JB2FsD`%u^MIVKu%0&>`rWnFMXFG0^*8nMAh wo>ecpXxuBf7yr3`{Zl0RE)j8I^ja?R)N>_hu+GbJTUb`BRK+?|{I>h^2f&a_V*mgE literal 0 HcmV?d00001 diff --git a/autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000001.gdbtablx b/autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000001.gdbtablx new file mode 100644 index 0000000000000000000000000000000000000000..8327f75cb45c3770a7ed555d122e2158bdc211c8 GIT binary patch literal 4128 zcmeI#F%7^l3b1>?xpt0tzUgfC36Apnw7jD4@Xa1#;r=ng0Q_76p6& literal 0 HcmV?d00001 diff --git a/autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000002.gdbtable b/autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000002.gdbtable new file mode 100644 index 0000000000000000000000000000000000000000..06f10eaf022bfcf9061147d1bb93744908a4f96b GIT binary patch literal 2094 zcma)7?QYXB6gAq)# z;8A!5-T+~{OYxR2V zz$IU+^~OQt*z?H6Mb-7=^oBt!GxJ*jEP<6%K)?<71|kpxm+nBmy>SK{y5N9-Zl`p_ zK%abNChKkL69SKFx&jt8is>w*bBaz?Rlu(wKYuqV+Mm^q(nSLeTPp+A#>zR~!Ji3q ziRX-lDRiCG@%$lymr>~XSEJZT{V1$49aGQk_6agk8!M*WHOxN3%LCj!+7)cJdWz9k zu=#Ofveu4*FEL3H;=T|Jw{t@a8z$;0x7ASdL-JIxT5oAa%N8x32o@WCbZ&Q5O|dQY zld@FDEhy}7n#f{`MT}!+v&Pb3(-`W_EGaKpQuqo?$#n|7C=Q&okQG(~v(9sQsc?i7 zW_DMQXCL-j8Pz_cqTeuZuKi#XOwSA}jV}C0_nXB466w2^e;eKE)o4j7>630+ts;pktu3xemTwMdgBmM-JmruWlCs%~d3 zYKyn1@mk)hQWD3GA0~Ov5?fWZ6lsBEUfFZh5}iEfkNSp%)OH79WGOgTyGhlKcX(gr z_j;Oj(@CguD9L%9sg~i2ooiYEyf`IJ68$>kc_8Xnb#^Zb>iPW)qQvnpc|%G_3jL5@ z6*1rYQpCA-$e#%wX{mzZb)I=LYI2gi{>8@rM(QDCX7bqVNv*~9#-0^Pi7>3~w5w)?kAu%Bgzy!o0Xl*TRY#9KTpo6f2i6fX;xPSxL5jqp%i#yPL zmpsM&#a;4tccG*JDVDgQ$By9vCsgS0z-A$3DA8a*5=v*Z_+ZaLM^tztj-&!Lp7>7t wm2|}&+qIPAf(9>)@NxkcZ~+%^0T*xq7jOX=Z~+%^0T-CB0MGpYpTKm(563+c?f?J) literal 0 HcmV?d00001 diff --git a/autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000003.gdbtable b/autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000003.gdbtable new file mode 100644 index 0000000000000000000000000000000000000000..00c610703fc6a966f3627667dc018ee21cd02043 GIT binary patch literal 564 zcmZQ(U|?Vb;y*yl3dAsA!USP?Lj~l4w7ZL=kAktDp`o5ZN@|&|p{aqXWm;NlQj%^; zW>HBc$OsmYa-exU3{0L3E({E8EKF>{3_%Pb46Y0jKoY2c14OX7F(fkNFcdSS0)-iv zIarZJA|WE|5e$(Gp$vHpnG7XBmFTLXpdwLt)c8Wx_@b-f2ALhgkPmc2Dnk*_EqM&d zKo-~zt|*)`zPM!Wt=;$jDah}CCNjFa`nx*^M=Jq|_;B~&ctcAI6D1uN$B&Ssltl5}i#6Z5kzxMiJ8ZnCo`GwaNx zn?=+Gt+Wq56rU7?D)m9Zhd%gLN}*7!pbv^rrHG&pK3Jp_+EPmO+&h!WPg82e7biR1 zd(QdJx##!JZU=zv`2H{ofPdao8F#ivT+Xw&W~4;c9}NjYC|o5cg2GgIDpsqJN+np; zOnY+)?QjU=aD4{Ga!`RaAfSQ`GDrYBxNTe+$`0|=-fdh7HenqR;M>b_i=aT065Ls| zF$&{(SVg%78d^}G0fPW8k8B%3z;Po~W4FW@3hEFP6rqJ4*zOquzzFvkOvJ&A_uG*{ zhZ-1w7P!A0*M66f*8U~`{YvXI+4#r{hX$iL~`bh)VQA7jkipOLm z2?{$dP#s?$Ow^)zGZ~s-yezgc=NJX;HBf@wF&G^!Vulna%{yUdU?c-6$Uz2@n4p&- z;OvB7A8@$AB&cN5>{-1AtjU!Llq$phtX;Q?b1S1tHW^95QQ1EEwD8N zVLTziP7C2Wg|Z0#qPU~TyXE{!;byr_HXPAoFOR_zj9U~7r3TknJtj9$CTXgGEG;2{0p zjW5sMxpFCf|FfIlEmZRJofW$ipSy28YGng>@6ELf_WP&iKm33`Kh859c>dteUtIii z9}?|5^ZDz9ySABr_t*5ft23uRHRA1CUz3T{+k3u^o&4$h^VkK;K+ib84dJ)#SAN;8 zj65fwzWmk4SDQEdyB}Crw#?kYlM#RG__g~xb{#d$SFLqLCA*I13P+0hL^1_%ixcPD z&4&L3F)hu|=K?tF0YA}IqpIokxj?y;4$cPV<33SJc?SHbp<4&+&2^$%bAeUcUO&L| z8yg!TVwqY^9i4)k~(i2MA0F{#)}!>H#Kdo{i+^1UP#FDgyKJHS<~Q8kI4 zYOgDLl~m(3rC|}&801qmFEu61Nt|XOYp6;?!owx7}}M76OpMcc%J402_?X0V`jt${I{EfR1blF?K!g%2krVVcTjuI9*H@Pe{tm`hFv z#G@kLM^hIUG`$N5BcPY2fJ3c%O>1{dAflh)6ZxJ(#A&b74^aE|((gA5l|(Fe=9BBq zZ?x(_}(5OtZCalj=&nTG6l$ZDLI%bA>`VUrI?U8R?L` zD5Z|2ihGuaLE#VIKkaX?VMHFk&3cJ`;M)Y;Wkot=(-FlPAYn*)jC7jcIu9c65|oe3v_=|L z7EkWbi>YKumPEdfO>vn#gV82PwI4l1eK3~yLEVSvZj?5DQ8oG{h~p4B0oGq|MJ7cE^IH8&Q1H6)H;DaI mBc_g(975#1E#=ErNo(RYSS}^qs`hg5LVx(ajQi++BYy+J(1Zy9 literal 0 HcmV?d00001 diff --git a/autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000004.gdbtablx b/autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000004.gdbtablx new file mode 100644 index 0000000000000000000000000000000000000000..6a69871ab4e6eff84923e795b3a173bf303428e7 GIT binary patch literal 4128 zcmeI$!3h8%3`N0+V(%7WM_bVTv>_9CkX+}OSydy=w9?J;rL%Jw0t5&UAV7cs0RjXF O5FkL{S%LlsbUi=3Hv$|0 literal 0 HcmV?d00001 diff --git a/autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000005.gdbtable b/autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000005.gdbtable new file mode 100644 index 0000000000000000000000000000000000000000..75dac36be0a40f1a124c90e00e6becfb82b76800 GIT binary patch literal 1744 zcmZ{k4NMbP9Ka7KEjXa^VO-oYPY1O)VTIZ;<`>YGQiK*tnM;_M>-DuBw7vH33T28x z1msH{(K(|)L`saykeDcnI+nSNWEvd{Vy3HPF53)D!Uma|j>z6ss@qF;$;-XI`~9x> z|9CG9!!R6Mm=;rEm{1TZD8)*j|5zdsL=|BK#z4XW2_sg6IpI7&!iNGK zd}xOYnBZjKy%YVzGf8kZ-XGrZ^uU^&L!WQCJ|U7f!KMFP0xbvZYv2;S*)w+?B&hc- zyOr5^Z|oc@3Ug_j88FEZm3EFUIG-iyKHfcWu(kY~ITVdB0G4($B#=V5rTd<=ZoyvI zBGLVPj_Uw=1F#VsMLXD?loMCl z2$q#WP3vO03%+eRErKCNm)<8sHE}K=I5z|E#URq5V`+7_SCwTtNx7fPiO#j^M5q;Eq@A>lw${82VIYzHR+;Tr4a;@Q zIx2fYP&lT<%~XM!e}7eTsCT?O)S_wMJF$g`JM2Q0*b;Ilu)`FPL5nZmN7QRS4sNK( zId;nN&^vN=47Ef?nzor}&sxZepRpr#j6SO|9d~d4VP1%`k=tOXtdk(YdPrA4?)LSr zIIV8IDSOWlI_g8|_!l&;_He+#!rJiJ4U;5Siw|$toYi0YRGc$+1odKH(7`zP=AQmD zqe;+i$@AvFeo5N4kwh(_inbG!gAe&&-)-GWlQQd*=|=Ho_54*76&ZljMv(;H9>1?@ zxLZFSuQ}47loduSeT=f=MK<^;d;q@;ntfv57s~U0&A!>_`=bN1pkJwMTT2ZWtI=*d51k4cS|qaKpl}0Fbu34 zA2%hh>%F#v)L#B6er7)MK8v!^MFc#NY?D_D*|h&z^## Z?|wU?qb3ibLY$H|12g_UVRHwye*mqlni2p2 literal 0 HcmV?d00001 diff --git a/autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000005.gdbtablx b/autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000005.gdbtablx new file mode 100644 index 0000000000000000000000000000000000000000..a9e25586862fa00da3c9dacc7c9da888457083d2 GIT binary patch literal 4128 zcmeI$p%H^X6h+auEJ36JWKuy~ka3iNNd*i#HijaY!K8yIpa&!>G7Zo~E))^ZUH0>caLXfa~NDUm9)n6M&`Qi&%9d~xKm8yu(2?)gffIeINWMXKovy{nGESb zoCgu)Qe$Cr0ct6RX#onbgfLVx6aWPofE+GIpiBu^TM|PlkOfl9z{9}G6#x{>2dgUr z3THwj7+F{u?ycST-WBMmzt4GN-tHIDcbu>2|IW0?*uy^HPAbcdO1HMhZc9#@cPS#-$0_|WWn<0z2USG>;xohtZED;xn zpcIR+MV3san^7b2A7jRB5_Op&bCI~QG2^Cy&MmUB8RwsDhPb(R?G@~4)+U#CzxRH> z-{<>&?{}{g0YHVHVf;klC-nO_I`~#7O(f$n-;i5GXcuQ@F3zx{>h#R)jO^tO2eR4H z?KCIUh$)n!y8<8@qAg&94S;|G0Zd>3n53MbEQ7M3F(p+w%>o?I;KUOG_NxRd)PNhm z1-wNE12*_T__H09W*~7K!rYHAHwt2nz~ZEv@H7W@D8i!+FT1eAnmuNecV=H?HJSfMc62qBc&I(*z%szV8JMhcWWBTs=B=ga};S2H|%GvSb>_A1IVkV3; zX@-!z6;L6fzYm+`p+nGbf8`w%*KocXS zi67r!VBwi8z&$2z?07j>x-`*rxUKAdx-;biIZJNOk{Em`a*+bETPrxW%2^R(;b$c3;Y(KSs*iM`uY#rgxD%Z(^*hn{~0yn&j8qI5FvR)eyxbLpl*pNRC9n^EuqG z0!`7_3oqdY3Izh}7G=2i@B^OqUvszn!T*4rb;Z%-;ZJuq79J}3W^~F=sf1j{yl@%$ zh^<5dM^k1bY+|{Mk>t#m%Na{RNErZHMO{?G!jtb!%_@GkC))n}iT7<=9(gwHJkW2c zTR`pA{I)++t}7{Amy}F8nn7n_8z&|FWQtR$B(w+|tN3tvoa7 z(q3;#(UH-E&UY62&`c|7b0HHGE+#H?PJz|P=(k1mz=Q9~G`(5ojtlwg=J`EC%c`=g z?b^i=U_79n%{;AHM9P zwObFIUr(93Z>aA)iW%hPBIbmPz{x4(GLkmjE|HYXl`9Db6TxV}mp#^VqoH+ui`S|@ zk+bxx6>lA`m+O(Ahgv$1CxwKcMkMSG5&N^DeOUW&Mq%szm&`qbJ*(y0ZU#6o61%~& zchuNfw`bM8q*CPO5Rd;h0#|^=@nl&-eH;8*iE!81VnqgrPxXT2qJUbFtQ|_}JDXReYy7-Cabw%&emO~gONRb>ERJvq&mhm0)Df&h MtcR%g30(mH0mIl;&;S4c literal 0 HcmV?d00001 diff --git a/autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000007.gdbtablx b/autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000007.gdbtablx new file mode 100644 index 0000000000000000000000000000000000000000..f639905039c53871c94a5bf234c33e6fe5e7d308 GIT binary patch literal 4128 zcmeI$u?>Sj5CzdOcVLIE#wAb#bzDY*E1?!TaRsIa{*{3=D^0M{Mlaj~JkmSW^vSZP zGQcWFscpNF1qslpTf?VGMMJYS$1dU{Olw^DqP42l){lK zXHGnLH88bIOG`~k(oM-M zDyak+!2(haG>?ga!=J&4!HdC_!I>e1!IQy-fq{*Mi7AsI1+0h>XxY8B``$AHmH%Tj F1OTrB5)=Rc literal 0 HcmV?d00001 diff --git a/autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000009.gdbtablx b/autotest/ogr/data/filegdb/corrupted_gdbindexes.gdb/a00000009.gdbtablx new file mode 100644 index 0000000000000000000000000000000000000000..2cae1126c73f8e0c12b41f5e4907889a14e63369 GIT binary patch literal 5152 zcmeI$!3h8$3= static_cast(GetFieldCount() + 1) * 10, VSIFree(pabyIdx)); @@ -2547,7 +2548,7 @@ int FileGDBTable::GetIndexCount() returnErrorAndCleanupIf(static_cast(pabyEnd - pabyCur) < sizeof(GUInt32), VSIFree(pabyIdx)); - GUInt32 nIdxNameCarCount = GetUInt32(pabyCur, 0); + const GUInt32 nIdxNameCarCount = GetUInt32(pabyCur, 0); pabyCur += sizeof(GUInt32); returnErrorAndCleanupIf(nIdxNameCarCount > 1024, VSIFree(pabyIdx)); returnErrorAndCleanupIf(static_cast(pabyEnd - pabyCur) < @@ -2557,13 +2558,56 @@ int FileGDBTable::GetIndexCount() ReadUTF16String(pabyCur, nIdxNameCarCount)); pabyCur += 2 * nIdxNameCarCount; + // 4 "magic fields" + returnErrorAndCleanupIf(static_cast(pabyEnd - pabyCur) < + sizeof(GUInt16) + sizeof(GUInt32) + + sizeof(GUInt16) + sizeof(GUInt32), + VSIFree(pabyIdx)); + // const GUInt16 nMagic1 = GetUInt16(pabyCur, 0); + const GUInt32 nMagic2 = GetUInt32(pabyCur + sizeof(GUInt16), 0); + const GUInt16 nMagic3 = + GetUInt16(pabyCur + sizeof(GUInt16) + sizeof(GUInt32), 0); + if (!((nMagic2 == 2 && nMagic3 == 0) || + (nMagic2 == 4 && nMagic3 == 0) || + (nMagic2 == 16 && nMagic3 == 65535))) + { + // Cf files a00000029.gdbindexes, a000000ea.gdbindexes, a000000ed.gdbindexes, + // a000000f8.gdbindexes, a000000fb.gdbindexes, a00000103.gdbindexes + // from https://github.com/OSGeo/gdal/issues/11295#issuecomment-2491158506 + CPLDebug("OpenFileGDB", "Reading %s", pszIndexesName); + CPLDebug( + "OpenFileGDB", + "Strange (deleted?) index descriptor at index %u of name %s", i, + osIndexName.c_str()); + + // Skip magic fields + pabyCur += sizeof(GUInt16); + + const GUInt32 nColNameCarCount = nMagic2; + pabyCur += sizeof(GUInt32); + returnErrorAndCleanupIf(nColNameCarCount > 1024, VSIFree(pabyIdx)); + returnErrorAndCleanupIf(static_cast(pabyEnd - pabyCur) < + 2 * nColNameCarCount, + VSIFree(pabyIdx)); + pabyCur += 2 * nColNameCarCount; + + // Skip magic field + returnErrorAndCleanupIf(static_cast(pabyEnd - pabyCur) < + sizeof(GUInt16), + VSIFree(pabyIdx)); + pabyCur += sizeof(GUInt16); + + continue; + } + // Skip magic fields - pabyCur += 2 + 4 + 2 + 4; + pabyCur += sizeof(GUInt16) + sizeof(GUInt32) + sizeof(GUInt16) + + sizeof(GUInt32); returnErrorAndCleanupIf(static_cast(pabyEnd - pabyCur) < sizeof(GUInt32), VSIFree(pabyIdx)); - GUInt32 nColNameCarCount = GetUInt32(pabyCur, 0); + const GUInt32 nColNameCarCount = GetUInt32(pabyCur, 0); pabyCur += sizeof(GUInt32); returnErrorAndCleanupIf(nColNameCarCount > 1024, VSIFree(pabyIdx)); returnErrorAndCleanupIf(static_cast(pabyEnd - pabyCur) < @@ -2574,7 +2618,10 @@ int FileGDBTable::GetIndexCount() pabyCur += 2 * nColNameCarCount; // Skip magic field - pabyCur += 2; + returnErrorAndCleanupIf(static_cast(pabyEnd - pabyCur) < + sizeof(GUInt16), + VSIFree(pabyIdx)); + pabyCur += sizeof(GUInt16); auto poIndex = std::make_unique(); poIndex->m_osIndexName = osIndexName;