From 3ddd31b98ddf623b4f5b2fa45b6c6c007d458b33 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Mon, 25 Sep 2017 17:24:21 -0700 Subject: [PATCH] Overwrite maxSizeOfInstructions in maxp with computed value. In issue #7507 the value is less than the actuall max size of the glyph instructions causing OTS to fail the font. --- src/core/fonts.js | 67 +++++++++++++++++++++++++++------------- test/pdfs/.gitignore | 1 + test/pdfs/issue7507.pdf | Bin 0 -> 18647 bytes test/test_manifest.json | 7 +++++ 4 files changed, 54 insertions(+), 21 deletions(-) create mode 100644 test/pdfs/issue7507.pdf diff --git a/src/core/fonts.js b/src/core/fonts.js index 36cbb13ce04c7..ecd68f8f9d138 100644 --- a/src/core/fonts.js +++ b/src/core/fonts.js @@ -1568,16 +1568,21 @@ var Font = (function FontClosure() { function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart, hintsValid) { + var glyphProfile = { + length: 0, + sizeOfInstructions: 0, + }; if (sourceEnd - sourceStart <= 12) { // glyph with data less than 12 is invalid one - return 0; + return glyphProfile; } var glyf = source.subarray(sourceStart, sourceEnd); var contoursCount = (glyf[0] << 8) | glyf[1]; if (contoursCount & 0x8000) { // complex glyph, writing as is dest.set(glyf, destStart); - return glyf.length; + glyphProfile.length = glyf.length; + return glyphProfile; } var i, j = 10, flagsCount = 0; @@ -1589,6 +1594,7 @@ var Font = (function FontClosure() { // skipping instructions var instructionsStart = j; var instructionsLength = (glyf[j] << 8) | glyf[j + 1]; + glyphProfile.sizeOfInstructions = instructionsLength; j += 2 + instructionsLength; var instructionsEnd = j; // validating flags @@ -1610,12 +1616,12 @@ var Font = (function FontClosure() { } // glyph without coordinates will be rejected if (coordinatesLength === 0) { - return 0; + return glyphProfile; } var glyphDataLength = j + coordinatesLength; if (glyphDataLength > glyf.length) { // not enough data for coordinates - return 0; + return glyphProfile; } if (!hintsValid && instructionsLength > 0) { dest.set(glyf.subarray(0, instructionsStart), destStart); @@ -1626,17 +1632,20 @@ var Font = (function FontClosure() { if (glyf.length - glyphDataLength > 3) { glyphDataLength = (glyphDataLength + 3) & ~3; } - return glyphDataLength; + glyphProfile.length = glyphDataLength; + return glyphProfile; } if (glyf.length - glyphDataLength > 3) { // truncating and aligning to 4 bytes the long glyph data glyphDataLength = (glyphDataLength + 3) & ~3; dest.set(glyf.subarray(0, glyphDataLength), destStart); - return glyphDataLength; + glyphProfile.length = glyphDataLength; + return glyphProfile; } // glyph data is fine dest.set(glyf, destStart); - return glyf.length; + glyphProfile.length = glyf.length; + return glyphProfile; } function sanitizeHead(head, numGlyphs, locaLength) { @@ -1686,7 +1695,7 @@ var Font = (function FontClosure() { function sanitizeGlyphLocations(loca, glyf, numGlyphs, isGlyphLocationsLong, hintsValid, - dupFirstEntry) { + dupFirstEntry, maxSizeOfInstructions) { var itemSize, itemDecode, itemEncode; if (isGlyphLocationsLong) { itemSize = 4; @@ -1724,7 +1733,7 @@ var Font = (function FontClosure() { var newGlyfData = new Uint8Array(oldGlyfDataLength); var startOffset = itemDecode(locaData, 0); var writeOffset = 0; - var missingGlyphData = Object.create(null); + var missingGlyphs = Object.create(null); itemEncode(locaData, 0, writeOffset); var i, j; // When called with dupFirstEntry the number of glyphs has already been @@ -1743,10 +1752,15 @@ var Font = (function FontClosure() { startOffset = endOffset; } - var newLength = sanitizeGlyph(oldGlyfData, startOffset, endOffset, - newGlyfData, writeOffset, hintsValid); + var glyphProfile = sanitizeGlyph(oldGlyfData, startOffset, endOffset, + newGlyfData, writeOffset, + hintsValid); + var newLength = glyphProfile.length; if (newLength === 0) { - missingGlyphData[i] = true; + missingGlyphs[i] = true; + } + if (glyphProfile.sizeOfInstructions > maxSizeOfInstructions) { + maxSizeOfInstructions = glyphProfile.sizeOfInstructions; } writeOffset += newLength; itemEncode(locaData, j, writeOffset); @@ -1762,10 +1776,7 @@ var Font = (function FontClosure() { itemEncode(locaData, j, simpleGlyph.length); } glyf.data = simpleGlyph; - return missingGlyphData; - } - - if (dupFirstEntry) { + } else if (dupFirstEntry) { var firstEntryLength = itemDecode(locaData, itemSize); if (newGlyfData.length > firstEntryLength + writeOffset) { glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset); @@ -1779,7 +1790,10 @@ var Font = (function FontClosure() { } else { glyf.data = newGlyfData.subarray(0, writeOffset); } - return missingGlyphData; + return { + missingGlyphs, + maxSizeOfInstructions, + }; } function readPostScriptTable(post, properties, maxpNumGlyphs) { @@ -2226,6 +2240,7 @@ var Font = (function FontClosure() { var version = font.getInt32(); var numGlyphs = font.getUint16(); var maxFunctionDefs = 0; + var maxSizeOfInstructions = 0; if (version >= 0x00010000 && tables['maxp'].length >= 22) { // maxZones can be invalid font.pos += 8; @@ -2236,6 +2251,8 @@ var Font = (function FontClosure() { } font.pos += 4; maxFunctionDefs = font.getUint16(); + font.pos += 6; + maxSizeOfInstructions = font.getUint16(); } var dupFirstEntry = false; @@ -2271,11 +2288,19 @@ var Font = (function FontClosure() { if (isTrueType) { var isGlyphLocationsLong = int16(tables['head'].data[50], tables['head'].data[51]); - missingGlyphs = sanitizeGlyphLocations(tables['loca'], tables['glyf'], - numGlyphs, isGlyphLocationsLong, - hintsValid, dupFirstEntry); - } + var glyphsInfo = sanitizeGlyphLocations(tables['loca'], tables['glyf'], + numGlyphs, isGlyphLocationsLong, + hintsValid, dupFirstEntry, + maxSizeOfInstructions); + missingGlyphs = glyphsInfo.missingGlyphs; + // Some fonts have incorrect maxSizeOfInstructions values, so we use + // the computed value instead. + if (version >= 0x00010000 && tables['maxp'].length >= 22) { + tables['maxp'].data[26] = glyphsInfo.maxSizeOfInstructions >> 8; + tables['maxp'].data[27] = glyphsInfo.maxSizeOfInstructions & 255; + } + } if (!tables['hhea']) { throw new FormatError('Required "hhea" table is not found'); } diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index feb4db9b5895e..e152161213ae9 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -40,6 +40,7 @@ !issue7446.pdf !issue7492.pdf !issue7544.pdf +!issue7507.pdf !issue7580.pdf !issue7598.pdf !issue7665.pdf diff --git a/test/pdfs/issue7507.pdf b/test/pdfs/issue7507.pdf new file mode 100644 index 0000000000000000000000000000000000000000..cac44fbaad3d4710aebf4bfd6176824cbb9d3492 GIT binary patch literal 18647 zcma&L19W9w(?8g;la9?!x?|m#9ox2T+qP{x>DcL{W81cEPxAEp%=`VnnOSSrIcKBl zSJ<_8)jjJT5@~)xDmrRrXaEB(0WE=*t|>GJ2Q-bmi?sm(4WEv^j=7Z)G>x>5k%1in zfPwAOUHgB+EpO{!@EQ1z@LMTZntT{B_>f`!EAw|pJ~cvr znANv8{)`Hm)YZT})a zPz;Qp*w2QRfQgocfZw+AqNaF{=X!|-v$7+L5(`cKM-e%eoM zj34|@Bt88Hg&sh__|NF?{9pP9>J#}N)F+kUBMg7_|841+|F!!$|GUP&90ukOuRd1v zKhght{IB+Z<^Jvei~Eujd{#_{}{b%ex9;VMt|Mz0}Pn`dq|IeQBeN7mDe@T)$ z79X|l|0~%)Rmy!V-Coa_fJV~F)6|{mu1%LnLToZf{^q@EHMn1Ac?gY5-01pB-Uj`JY=N z9HJgS8ktA?)&HC$APNwK2z25|lp~CRLl*QpX?PC=$)b`E$K%hsb2={&VOS6me}TB7 zp#aBH5jARqgO=c#b-qeQc|;%nii3B5-wbnvQ`w!Y-+UBg`N*Q?)vCr$VnWHqi7(cK z+ds@nCYJCPjE+D2B2S~>#T_(H{K|B%gV$H)`lyhlso?6GRmi=G)+b;w<5~4&9TL$| zH$8ucCf}0Sj{EHFp`2+|y|*5kHBMIS&N*&e*m}Q7SFe%0e2Eoni_Gn&fVX9o3YODVt&j^#J;V^v_f*n`DG~fO;lDA!!k8k?Oppm$Uvxd$UV+o_Ah$n0J^yNq~Ad zMQvoI=C{B*m8l(*e7aY_qtcCZ7oWf?^f9gn+k<_2 zh+pD14$c$1tKG#O3q%m>%!t}It5HVAxfypuQw{)}(Smj$oEi3v>zwP1tLyc}-r;C> zno)&Ng^^d(8-yVT!M0CrC`8);z7?hBVbgW-_-n3P)_#*h`SNs&khT*>-$k>Z#Jxx_ zxqIAiVAwBdxIdKtUlaE;SN{K;N;)Pw=8xa?zi0HLGO*GyGyRXs@o`KQA>`wg(B96{ zFu_qm7`jrkm_S0O!h{phd_$+?e@T2H5rX8`i0_F6V;7RqHD5qX$gU>3!*dhs36z<~ z(YrCPX-R8>u{wtZUwyG#8)>~?eP2EAaQpoX4w{Wy$QR%vLZ;baqK0Nry@wZdQ|`{E z^Uxqv3v>m>@1ZyeYVh1yYUF)H5_L5hpm){C6s`rvFG5ZBNbI zA6*d&R|O6}f8nZ4O)+yws`CgnT-p4H{GEj3_d6MFPx^gYrc$(lcYlL6L2dl5%448N zfV=<)zRBR-kWt`E`b)jkoAx5IGy*v#2Dgs8XBQ=bS*T6BwYuacToIL#iYAD%fiG#` zP&S<|`t{oV=y+@^1)}UauUR}GFwxrSed$rbS{S5@-7=9L?%l2mB68VQz z2AAF4%Huh;dYk>@(5%_K)k@p#D?%f7b|Ku!ATspK3p*;{7o>qQhzOZ}wn&|PI^sPF zdqLckgpHzoXd}|r&dG|5sNS9UoY+E3Y^;fVS$)M;vAqmRoWnVq*&_zuZj^W1I#Q}U zqn6duLfzG7G1{ZfPWRVry4$Y&x%dO|ZK%u+CnAK4gNm1;J8EcJOgW542E!iMksZ~H zfW>6LX3}1ck$zxG{rIpHd@+_9L3iH*W5;x6XmUh0#+#s$Cjg`ig!Z@=Ph!kKN_$PLoSO%}-wV#!U0u?@&8)kGZPeQwSlRoE>#tK1kO)wQoc zwlrA+fx!uBCKz`E5V`Vayltd0>&wm)Qz+d0U* zc&%ImzitjaX8C}o5+GcsP=2Mp;waGhqIAIk{S)5>UP~7~fJmgnC&^lf_6bns!_9*1 zaz%ITuFM_cVI?)P~3sgbQ37> zEs`bK8h7!aWSHs)D856G{J0GcH#u71Nw}gWm{GwmXA`m8E)hL@ZI1%MRr_ZT!qFKpOeSQE!U^CiIt`wDTeS!+dQGQ7!>+=Wi8I4IYMicB zWhmne;y9LH_~!=Hu5!cUG?7N(wm4iS9jlYk23;6pJp0TRg(vO5D9A@)q-U$HByGx4 zL@`>$-_s`Al48$Yk?##FJfuJ6q^9qDn~dl{DI4Hpm_mIKelAu~M`Jb!9*H$QB-$T> znM&6j=GuzC(J{nLOtg-EoDvyB@yt~vW$++w{If+vYCDECj4 zl@>$W5fUNIA$_DMkrBi-{+ckDwz9hnaPukz&_@4AoMPNt7C0%=CDuc}?Zq03uX=2t z{3C2=n(-3QR)Q2oxQn~@g49BYvkPQiuuaeRG$_s%-X|O(Sb=mw8LD8aU|CHas4kSW zB16Z?skVzIBLhF6*TvLIL`J(nIx7giJR_Sevp5}Rx*Zzt>Hmo=%pJuc9 zO?x-jL{vr4PsGpS&&294=+6`|)mjqegu8@sf3&H6s(*^o)6J#^Yf^eupfs8oUP#tA zPm1NFHn6%=0=e_3<>7#Db(iq`-?=XxA~iAmJ? z+eFG+n1L{%HMzE6WUE7_;g@ctb8Y<+iVOQ3uqKWL&6v5EeCgclHzMA3)`K1xoKVRs zmGu$Nn$`KFn=`0OC|4(NgOWW}vu~ojeUTYl9E|l=_Rgv;UD3(K03|cb_@Q!= zTIP~ucFeqx8uN-^S~(`(_s{@4395c8;4S@gl&?abqe%l?t=54cdpy{#}dqo5;bWA zj5&lP{J9>75HUkA{Jx4DUl4?;EaZ#>W3!ecVxBe zzq6b|QMp>XRCn8d8GC;jZC6X& zBNONq?XQ89Kp^!~#;6m~?pHS~j&tHTRDle6x$IARa1=U{PMrG`rZILBy4o>%U26Xc>t_|s87Yz)*4Sg_)cNot-tH)2s(nKNEy z)xxp3g|RNX)9Bgl=n%ved|x4mODn#Y=^&yuDIzQj@LiUuDF4QKNU5v<^tPGia6bzC zKPUIRP`4mZw{AYkH)}RGKya^-F}HK76~5C_LfgIs2ps5(XGek+#^3Y}QzI+4_@|`h z7y0cVEkf z4|WC7T7)PiNk%eGMy3YhM&@G7{&;Caj+z>H9sR1?Sp}iyz0QkMju!i^7oFgn?cw+i zGVSqra`l_G+y2snd_{{v;)|>A{?}1{CM9eaMvbvFVHr5N>6Fx%-kNkO`PU_k)%!Vc z^uE)?CdDg*z_2UI?n%Q&kHk5EBNG`JnVcn~lz|+XNDU1Sj+xLq5B?v222fN^PMc0X zzVkL&PwPqX!|OmOGuCXCRJ*G7GMhE z)C0uB^c(!sJ-T< zEE!W%HCHa$+GgKck|y-%5_dfs2QFx`1!{SBN`Rdhq!>t&$i zi}tPqM5&eRm97&Dup?Z{D0qj;a!-4+&0s2!mV>lx!dEvP{C2W@{@QyzL%X7MlF4tiK%>y z1W>GHRwBm);OtxDBb7XP3*!s(K^RDS9g?`sC~vx$*y&|UrBR_o^vmzK7imyY6EYfL zy0V!Xm*Q-)MuyQM7ATibo=U0#U+k}HAikvh&wWS6M0mc z`bO%AHDTL|JMNS--u{$B&~XjUd)uej-oCWS8d#X}!)cs3Fyn5@?Of-DdTm9Rr z>n^lc!{k)rh7*DF(!%Pq=!^}-H>m~hA~9YHcW@8jW)B0Tn?OKz5Gc3u`zA12T&~{i6 zU=fSUHWA~Z>X1F)^0A(c{cMq5x$%BBei#}TsqkyTj8a-+@n@0|mB*u3B=)aVSuaM&)j?`a@9H0ey*D}BVI3%)6hBW*Qb03Q*K$EsWO%qCVkVRxWMMKFd$b0`gJcw~3#5<{@%%-l+6?{{?C z9(9C?s%Wvhf5=s0zDa4;@T4Mr2rV`$9eRXXVU}o$C`YESK9NdyKs5_Bw2Z_YibB{A z+P;Y|iMw>D`k}FtT7+_ZN4p{s>5{ba-Sq`iu@@>g| zh?jQu?e{}z!Yuj}NLXc~k}TwVxV<1Foj%Dfjew`c+@Mu&%vInh=)J1!Z9;8q!_7(a zD2sg`@W$vje`!JOp8OaekB1+E(u%jOv@8#`f`a~QRQ524R!rIBruk7-9_gbMZU%L> zYr*}Pg3`4n$E7+u5w}A%N=Ne+tZoko?#CC6vAOw24ek7ZUBOX^IT~V{A`eF^mb({S z0VMyXno34>A@p+g?WmbzWpW3VNV-upfl2>+&W#L+wdWbF@9g?_O9ZtG zoD)anw`skY`}2UlXKUY-&NppUI8s3ZA+eb%$lhq9gb`G^i3c$2YmFv7ziv=F%D{4u zpEVaRx#%yk^1e_mFos(M$eSXEfL9~<_Z%`ShVuxBo}jNLz$1Tzgmn!eKpNGu_ZwT< z1q2Nn@Ed|U)&r`l`~9Hv_t$#M0#pmuup)(&Y@y)3tFTd#EZ}c*zsV2gkJ{9Sw%O7c z?bda3FD^JPC9J8gAC}*d(h-uh8zA^Sl_iuSI)cn9>MvuSapU)=?p;{s5Tf=6S*4_6 z=$GiA>*l`cnk|qfA=64t8J>BSE2){|7@=l9IvE){89IL4`yBwc+ml{Rw<^u5?ebQZ z$kPc@wdm40U&zvUCSFLCfFHzo(NBS;XoNC3vI_FjDE?msAbCV#$iQSb!0J{(3T-dyAT?;)ZY;O)1_Udd7v&#I!&z zPa0E~wg@cU-Fb@8%LTVkreuFl?vBuJL4S_r0zxVbIg!8VMPTCyx~(2IDaz#@&KVm3 z@1#;b;_R5U-@oETY(0{~#FEVIy21B5;?IIQi8(eW=T=}hP^iScU4X2?l;&m}>o|jP zN1&{draY)mBp^i5t!~oX_czq3W8)#n4Ue4obiq|ZkxG9@>Q$iaK7F>PN$fb!4}!4{I`scuTXbx~n`1<&;AYFF4& z8j;>N<)F`ujfKi*Z7#J)a=_&&8&a;%@Qk`E^}F6LOd#&;rJp;}ZUri!NI}FAnz#x) zES#z{Ni3ahKnx?abj?iHnXz+Ev(a45y#E zTTTiMTrNK^KC2k7tnM#Q_tp=|Rs7fMH--${G4^Jp1ki2!U7Q1_kw=mFRaAfqX&AER)$F0;{ zfKEfllDbc5)4-sinH14{vyNIb%d%Kv!roU>9iCnEFrF_uHBk6kwp&Row$&G?Y>ocK zkx%RC1>^c=PofUkI2|}sGef*n?aWuCaK>Pu@W-Z!pDUSpby7FAYleL|&3HLBK9L9gZfm|7yUTe9a&{1jze-Bn`ppQ|UlyaUCvRh&Fm58^UW!67wA znfb#AXZ1vVI+8zC`i!Hag|ek{6GIACT{UNT z8UO7M>q%&i!A=8iLX``vUrAsur!S2W1kQaA_6VXt{RvV2(ww$W{EDrvNw{~<`OqA0 zCBALqGJvIBdf1jZQ*_5w#k}{(OAN+TY(=)L$o>=-ijg-cjMEi}3e%h=W@3@Sghm{d zquV>zHQ8QXwvY}$gv|X_b4&VJ4a~%6D0h5Z=Ek%=hV3D8xu$VkUIA0s2%*gvX z;;F@GIb2t*Ax*A5VD>xZ<_>4KE3SX8BF;E9bn0F{vItw*UT=KoIPw{mb``K)R%SYZ z<(L4{i&f`6YpmiiKh0N`@v2RYwm6Ix9?rG|F@714c4xRV{%lWyGoEj17sy_|#g)+S z95+Ev`X_F8@EzdW{XI_DSHPoNN*D#2rE&$`|xKTLBD>7ZLpT8Xc0PAS!yDpeGz zfhB&*m?N@XDV#h@wI>QPoIjZNfb_&N(z9XLI*u>p4c}#n)R8u8bIDb)UIY!*@=pg< z%RRsp?d14TavYaIi^v6kKkZY*q)nGQS4`2vs*tRly_US~|2oruD5bOZ@~vx!nBWRr zrw5;x=84q2fxlf+c3yIz2|YLsLini|FE58sf$3J*JQU-GC6ytB_RjqpDiXjl*Bl5B z5zUh#Eow6}b+~B%+o}J|IG=dYx%t3w9^JH129t)`0ip;@gQ{LFEFpraVw5XMl9-=8 zt$?xOMDNY#>1qm36iPMcm;7vm<338TjpRm5NtL_n%cU%?Z!~3E3voX!vejFLCsMNW z4-pPn?G}gRww6RLX z-M}~_4C)Hjz?@)8n1KaV>Ld!tQ0R?X$|R1%xu(M<)oO-l4d!pQFA~tvmghWvwks`# z!k3`Kp_Jp-s%#m1z5o`DUUHt~JS*-UcYoXmU1h8kFWyI|(>DL})xfv5xh>pn*0cZ= z#{xA>wSoRh-Y?KOd(f7xf*E_8aXgF;c3SIDahz&OA!`|ZM!r;DS&@X*!d25^k&Lk4 zL|HZR9x2uE$9B2}O+1wv?IF`qbu`W(dnB&6~R_gYHdW^7Z6RYN)VA%W>VT5z~2+r8dkn<|wx3?D1%I z^WYgR-@M>RF`7utYtaSab<)qh=%9~?$dN)pF48N37}MDn+)No9|Cs*VTMsF#4enh8 z%QJ~LJ*o(p%zulA^0uAm0au8|99=z59mRM4C(8srFN#G{!yq^@hBm19gct)Jf~JL+VCFOKYMASLDn(IO@gW1lCCh{e zNEyYi%5D`-xeBD1g3ZQ9L^Ryz%%I@y61cj7k7L9==*{s7CBbmv0ptr;MP^FC_prK<$%*M*qIKG9S zy(v%HdsNGUx1KhrCic(D1tOU-xrtd~_HG~2+^kE8A{r~llA@%;gN#>z2pD;1K<0Z- zPZ%kgu=UF;2&KU3$F6vX(*jnw$L@uTnxvjhvLVQTZ9%3szTcY6^?v#IuOM$=RCg1Z z<%k+9yJ7wUqxXTL)j zS6LRt4wYA0T2MQI$;k=eBp3t_1MjnhwWKg2**xG3+F)T;BuepoA2d>k&?yl;@5Djc zcmUh$%RappSLYC0MhP;1z?~%CtU)xayFWnj6~CO>CmdoBP}7wPC^X9GwtK;+^fa#- z5rU}Tkg4jn3HF;a6SN0rgOdgptym}{j~UiFFFY#C-aj#l8xC9W7m`!A^&~wgg=m+V zu-w&EhqcsNR^OpV%2jQ>NHPJ%W@e8FC+CDrlC!Hw{+!hI4=z?5RMC4H;@W0g&xXYW z<;dQxgiS?qq&NeyX=R~#|MjgPt#<{?vce1P^}M|wi1CvK0mn?HXlN`@`9zLFQJHd} zlMP|jv9wsjy z2;WE}NN+ZW!f@E;>;Tvzih<9t!=BEbxid`T56ex4IJYs+VjP;atUUjxOHE3t?*j>g z)|lmb1jX73P@DD+e!`+_vnrRmZ&EZyzhdJQ6?IisH(07?)|0c!T7shR%a{m!huYVc zs=EmKVCW#hgS}2(1Zyh~d)smf#OKpfYGFP1@oBwN7}2iXIdZPGgUPAc>@1nOs|3Zr zQ9yI}0~!^1gufEQ3oYa_PN&y*fgq7hH^f4XKoytARI07KB5*+uo&sNk+OJAnkZpxf zitjMlr8N7Kj}+xN=rj?WPmg%wv|T}tm}Hz$%RI7fEVgn`pZEwbV}Y*=Sl5PZ4f6M; zX}~vf3f+MuBnxdI`%>8Zup&(Ba!bBumRT+c-O)f~Wh}YW!1A)>hPa%_jR-R?vo}?< z^66#UShdJ)8HTHvORRq}bIwCqa_g zNcPaYVKOZvfw(qS<=nG0aEaZ>Zjcx$K$*^hqQ+|Eyf%!E46j<2OfIItpEQ(CBZe-S z&R>`-OiMPPq2Cg;_S^p%9fRdE@LJIQ&VH33Gh* zZY<%cO2v-;?2NL5->p@fjTg6t7^MSnQA^B zf8FqrWWU6~CBqMcF|lZ$J8-NrpEK>%rLX|g6KpNxS9pMPZaMa2O%7%5Eo0!+5#$SF zh+`s+#dAL=gYyGEgPFoMopcnQ0_k#$`wlct$c4AhPkr0v$X;*5o~PW+znhmpol($xUH%gaS5N;D45f)t`JkJ`&PG!=9oP25lK z!WiO^htkDCA>a&zsW|ubreFeLVr;wB$cfu`XIdW*KfV}`b~~Gz7K3Ma25|uQ3G;Q# zdr#J9y|q&i?O)&s7YRr5mBqg$lZ4i+W!!9V5_m3vc zh6F}}E=Gk0E|KZYt5etzqCg~1h0Z6J^&}u9l_%gQkC*2`Y<0gM3qO@Wb0j%mz;io) z?6}Ub;~HQgxp}dG)M&kav4V}V%Ybu)Y|)s|n%eYEb8^rP;6L=tl2m+db@B`~AjG>6 z*PcIVOOQnwsqV5CkGvr!i8W7CoE1M95kLPreyMx`c1D$ic>ox%;iX+ma84Z5FRP5( z_)T~I69FGn6(tLNKwcQu|2oVYA}an>uf}T&XttSQB>}htJv%D|s^gjY`qc&?5t?|l z0=TXYmpEF8$;Ys)4}8^VJ!9TaM0*nW*2RVeUYp|-DzIW%MV$)vEoR;%_2xHEo~IgnaBJsO{`)1O)Woa=m|@d%nIyA9K^>9gs~ht<_r7{HaH`!lm0I-46MI z3XMNrZ#oMT;quNwxSqyE-$mVNTMABCRzxJe5=z#Ep&>()M8Q!9fo8HNSDkTVNDyD~ zBpW9f-jLkDzp*h82TT91vfHJ1X)>jVDhQ$psWb48KPBv%vQO(K*7V5R3`jNQwZJyJiwW5IjmG1*LzT z=b;$k{s-maN&hr+5%ozKPOBQMSap(}QG-%S6~E*vzIsR6z8?CRE#Ex{bISdumsHL; zg2aIXrlgLaDPPp(B%G0{Z={P6Ij|W9!66mR;g-;QKkKH=$kAQle*JT%a}>WD3MVrd zpjZ2w%rAQWG7!q~2Lk-UEt@%-)W)t8=r>?topfV+Zc+S#{TKJP(r z6#jbkBHtyqGe;bq7lO7hYs((1-ccPwcXPQBnD;I{qGJ>r75siXkC8p(ThEdnyR9LO z)xE9k#p3w=Q!*_gl?~;&Oh)vScAZoA%@p(xvn< z*MLzV1UQaF?}lKSsxny?gR^>AaQeWPzvCW-HNlU7Ds|ZI*xs(pk)2iyAUxpd&U0)2 z9&7tzS_kVkr*nhiil%|hb+Aj890)rq#8vzC3U@H5>9Na$eU*3-ol#C(QcS@G&mzZRkJpck(BlOO;qeAk*-sEYVEc5j5lbBsu9F-}Ojjza=m_J9)?J-PNQNWnt^yAoUWrDO zn{C`+K!$i^>-inNt(0f&g}8-fB~US2DeS@=?@3XpY8vVZY?J`@*B)b&*_U&nO$E%S zbphNPsUaHhhu#TKFMRrC$)+`+^mH(A`p&Mb$?`k@qQHZq%2+l^n{)@e#BdKQlkx;T zBVy3z@o&L>WXPim8hZJd;}IR5C^Z`{VNp(ERqJ-om2MtJzGg|+;%n)Zqbsw_?5miq zGF1)x5HML|{0st#9)UQUV}MJuh02kgD-{i?!U&#rPmR!lN!8}?W^d)HS-FYvJNGi# z5c9Hlk3(^{l6*23JI`}uodFrc3G%v~tqnm6t>FI9{;3%2k{N*i*YR!HW^!A1wq@I? zS!NsLr+B{Spv6gfF7cu_qFEp2b~wa#p2qL^qu-4V9d~EZEM%9fA9prACYpUsn``R{ z6-FiqeSQW!k1v!Orpm4AiXi!TnUYdNiC@DKj51+WSe6*?sa0D;9=nnyPe3mlK?DPV z7G1P@cOr~AyDDGTus<o^v{Vcdm3ZKp)tevPD8#6@XP3}id>Hk5zys0`|iiD1vbG~?^1c> zFS|_XPWEQ;AVMZy{{9)8;?oH}^uT%T8xxaY955@rW;(>Ccy90q@2r8#~_{bewrv#|7HeFuHJ z@;-!~DQiohN0R86I3b-Nv^8yh<$2R^A6skq|r4wf~J z0$suc%xMOSAY^+@9z6)oVn(r{(*KZo5{%1H!zyBZrp673^uDju=)4ZNX9x$AtT`cq z4@!uFJf)%Dp^Dj0)~zlU)v=wrReOL=mk;dl&{58j6n=)U9qDrTl7&z5D>TUkaS=80 zPdmn0_+&|xG@gz39_1<;6M^w6qK7dJ06ut)_}q;%tX|L+to(gDbJnX)Gj&Y=ycEUIRH8UH5+? zg^TGn#*S>%{$vzH*t5(Bt7G-8@on6iD2oDzJ;UTG0Ze@yj4KTGJNJ@6z0+0d<~hDyIOlQhONYbXXEws?srH3z^}2-GdH z_1u%_{Lfy!@Z^wpjoBtg zku(yuLI~E^9kHf+os8}`tbm>=`bM`{uB3mTJnYX{CJYoc~jyeT;UjTab$3<16&)nshO}@=t43&svg|6Yl}+-4+D1##AK| zF!q#p&ff#tUw)4xT7sS#{TU8@V_fb=8*Ax48AKSNT4IbT#OAT4*N;8z`Os9R)4GBQ-n?#F4TMo)^cq_THL^( zlnO;0N=oN(T2AGc5TH}VOL!ZP^4r~6pG0^KlMePt8YbxPXwbX~y>HlG(P&5ZknVrI zxpFX5lPdDFozk4mRcUaYG&M-Fj5m_Eb<_wlk_r%&MBO?Xg@<3dK>%lMTy z4ZDveVpT1cf~V;vB;;t%4d4#o2#|f0Qs=?V3nS>4GVCIpuECCIwNPQbE~m6ZIij=< z?r$)?bh(H(?Z8@U@M0*sGB`|7Q*Ic8tZ|4QD_D3ocFrqacrMv^oKP*_>F-;UAsnYI zN+7K!x3c%B)*jmmq9F}!Xh&T~o%x!gtTNR%wi&|Z5Qv*6MrNoS*2_yw!)B?J7l(%V zwX!)_lnWf|^p$y!#(!V9sH00c(832TT1XWoRw>7xYH64@CMk%2d}b+dN6 z47c)T%vfo0?YJLHIyd?%8_{s=2;>%mVmheXhmg_7|xs496$N!N9#9*W}%jlLX``d%Rqa;JGmh9 zUN^p{+}u%3idWSzIUFiha6^ycw9Lu`9+OYn9qbx6FsF#r6ht&Tqi|aA`WfCuDBc~6 zh9t0)39efj7tA7jxz8H-BKY94OnU~}HeC^lufJr4^1ajzF}oz535;nVjg&+Ux{s2# zk$0naqfeH&gs9OM-#4xcq#Lw>96_ybJHwqCw3}6V7D9^6pjoYz zqY`~D{`%hmZg8h&ofv)gAT|fw0qT-?jzG3hOHzD}Ul5|n!3f+C=N~xM=l3>SA{|>Y zxpPEt`(EHTpy(wTq14gOadytD*R?Ap7>H*jC59s0B}P=B*^ROrfyn6YSVQ)uzO8zD zVm}k6LtVDpEnm=`DCw?Hg)9$}-$-I|@L>fBsdqnsbfR`9BaHW<*!H3z?ah3-(9lMV z{!W|(v2ooIwtwqR#eu!MKK2%VOQWX&u@mnoNeN8GcLp{FQsfhM;HJ!u z-GH!wa01)`?vA=KuG@(Z#5MnY!;YnOJDP?24reWj7tasJ|ApxS;-LE{7`Il%XotVu z81Eb3GyI*|2Kj}OHkCD`Q3sMO==rY_nwqcq0_=8oZrXIeK#YF#zEhX?clgn1bdszp zbwIp8p00kmBgLHP;3vl>4!a>pDX6$W(0gMruUDzr;z;{a_*{2p^)$OB~I+>xandK|KhWzzz3IH*Ya8d ziTIu+xc8X}2G)qZQ~nY>ZC}#WDjl6=2Gu*W0rSa=pGkp=`wUBLdtC!U8x!wQj=uvV zfvHFOa{JFgei-K2*<~^QY*ft8>7ytc?jtD&L5I5)-eRX_ZDvk<8}WgeiA(pr!#tMDo!!}TEQ!c zt54EG9hVhx&;s4pplDom|i)2@VopN{J_ax zBPUEt^{6(2eI8I-1`vWfTIOv*^%=9Hw*0oG{ za;G|Zg}^xcnjx}5b|H>ztwzhom)^TV7JR2=g;`p zSvv04G#FM|!wR-r@s|NDdiuN(R$|2^cX#%(8mwG(R`YY5rt1rLmm!-L-$Wd=*B7j1 zPu1$nY37TWieK}V1N-mb5lWD^j{@7f-DZS@-UU1|0@YZltufx$9jx^Sz6R)H=baE2 zq{y-tgb0dOn=GgmJ8sK}$ofn7p%4lXqQVuA(2rkpeB4G3S!GuHVF+C5`>z+Rb1j*- zmHRDo&y~+ELW!sj*ep$&GD$hNp;(L@2if3o>`n)Z^%_|%tIJLlWMr0VQ)MmE)@zxEsta4U zWajIwMIJhyBAcYt?s_7ws7#){0YVjpCbG$|>i`S&`}M~iZpM53R#KS8vbS!Wa8+VMOKa7eRw5Jyv5JxgR2*Lqzc2DLj~2G5Firp2Q)C|BQzcQb z4>QkEGZb4TS38_rR4pqkwT!c{Up6mWHeg@nS~jbfpT@26J4?o`cP%xGn3>3^i91Wr za7a4IWt5Y18m&~NsJCxCDHI@^TCHt8i{Z2%KPhoDpjl;iJLXyxGAn90OY?B}eNyBg zD|B2~d6xBB&(f<(b9>{BlYJ|vg)ri?L;zQ39bwkZFe7M^53#Rpk>0mNEKz42WLnEG zy=PKMHN~q|Sb!JHcQb)gS}`T6R#cCd*j*>FWV~EA`$wVtbV?Fod~=EGw4RUc0FjlK zy)e&F^v7xX*b<3GomtCK46AI^kjxU*YMon)S=7x$=3z zVHIAQUcJ_n$@|Uxwrx6I)^GF^FvR-yGxx4-dlU=rHs20E#eaP@GgnhfU$r zmzY(^^gL4Ihir7nx8dnIar7eNBPndGaku5^1#3P%i662%Iu9{=h z*LEF}tjvq45=zE#4T+DjSqmwi!0SF@$~qd#O#vC7Ym0T}QduqAi!u>%GUP zL@6JyE1BeS_mQ622Zu*eW*3L2-Am+%lWwm3IKsTYVP-qolQO-p z^78{`O~Wr2$-((gD~!kDmimWEy52gU^7Em}&RTOtgZmzND}`>X{N$ONiap0mO6z~0 z*-KjHzqn;QUb@uX=ek~gwaMEs^1{l)k)g83Q!QrnXjbyqsoXCm%irXDyYzi=qH{c$ zpWw>#f0x_o2>h92ReK^^6l$NwR7g49!GmAB^!~owE^lBpXCT!R(IQXv6`2aEoKwNV zH(h1^E2EvWf#qSV!6R!?8hjO|q6O!@VDY@G$!{I)S_ufl1Bsp|gtSCo-fBMKbOZ}> zU21=CYbPD>H(RSbTLndxuWYsON9Szt^--6>-{0ExIKVd#5FUvjCw%JF0_3EFMXjzX z|5dSbA+Ykd6?visCGrLP7Jh59#Jn8Ue@3t<O4WJne+qn5c>6X)Dyg zR>rGiIO?MH3A|du5_wv@cuugyaum#Y6E^LFHy_G6yx1mK_HtALgUr=<5qvT^s>hCZ zyf0XyIck(aA5DnvXkHC7I$%Js+s#q2Hhk%vpx?w%rx~(i1ZDXz;OC`jylGm$r}6>+}g+zv37h3 zLVKE{ly-b@QY7OzYBz%}SL19*FdJ4d2_$G@kkcV5ck*-ugHnDHNeDciL3P!5=sBKF zhT4QkLR?dJd<6W!Wsecx4GwW|2Tw~`0{r{#h?=ZGF-tV*aQTOV zUdB<^8T1Hl0ePOZS#T=uV|NXr70N$5*z2uWFCNiJ6aPbDm6Z;;j?A^%As z8qm5S6gT`8Lho#lGB)%Ip?t!U9C$zLy+Smeu%rmVOTxXKct}>BzH`=_+Y*@&Wa0{{Zcs`|AJz literal 0 HcmV?d00001 diff --git a/test/test_manifest.json b/test/test_manifest.json index c724c35d7caf4..5285e0febab7d 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -684,6 +684,13 @@ "link": false, "type": "load" }, + { "id": "issue7507", + "file": "pdfs/issue7507.pdf", + "md5": "f7aeaafe0c89b94436e94eaa63307303", + "rounds": 1, + "link": false, + "type": "eq" + }, { "id": "issue5501", "file": "pdfs/issue5501.pdf", "md5": "55a60699728fc92f491a2d7d490474e4",