From 506505e3d215fb18d51d509a9f6265f2e8aa01b9 Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Wed, 22 Feb 2017 14:09:35 +0000 Subject: [PATCH 001/699] =?UTF-8?q?=C2=A0added=20test=20cases=20related=20?= =?UTF-8?q?to=20classes=20pattern=20and=20matcher?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucas Cordeiro --- .../RegexMatches01/RegexMatches01.class | Bin 0 -> 1272 bytes .../RegexMatches01/RegexMatches01.java | 25 ++++++++++++++++++ regression/strings/RegexMatches01/test.desc | 8 ++++++ .../RegexMatches02/RegexMatches02.class | Bin 0 -> 1273 bytes .../RegexMatches02/RegexMatches02.java | 25 ++++++++++++++++++ regression/strings/RegexMatches02/test.desc | 8 ++++++ 6 files changed, 66 insertions(+) create mode 100644 regression/strings/RegexMatches01/RegexMatches01.class create mode 100644 regression/strings/RegexMatches01/RegexMatches01.java create mode 100644 regression/strings/RegexMatches01/test.desc create mode 100644 regression/strings/RegexMatches02/RegexMatches02.class create mode 100644 regression/strings/RegexMatches02/RegexMatches02.java create mode 100644 regression/strings/RegexMatches02/test.desc diff --git a/regression/strings/RegexMatches01/RegexMatches01.class b/regression/strings/RegexMatches01/RegexMatches01.class new file mode 100644 index 0000000000000000000000000000000000000000..4006de70b283584550ab36dbe0f60853d85c75b5 GIT binary patch literal 1272 zcmaJ=*-{fh6g{17l3^er5Ec;)iV&8`0)zlTc5nlv#1dJ27?L&&CK;TWSn?mf$Pe%= zRs~C|^xZdq2)#352}{`z-M9NL=iH@#pM3ubUe1oFJrVcO>BR%<>=Mz9hz~vJ zwWK}~{g8d|BkDy=L>vhL10rhCAz)CXC`kds3=N%%VQ}44wW2Yn8p?K_XBpTAgJ)bV zs^$cPGt%>l!8NO8IfH*uE%N13VVmnOEn`v?6t&3E6xm$dRX!-Oyi&}?R!v}q;w=qU{b)8glWu3n8locc?k=6 zBq4|fhPM9%p^8X&j3*2&7bToN>&v{ZYdS;S<+2EPD&ZL>83GqR&$oAZ#-uvgPbE{$ z$8@Whu@%KMxlV1WGOqOK2IETU2~x;tg+03`a^!~QR-Ue-P#c7T-9CyjSnWBxqv)&r zeTf${Jl%86{}h<~U2oMQ%^{5*O=30YeZ%AhQfMVgGgOJ7YOxg>Hh2F$L`WiO(Uok`u%iA=;bh)=np*)7^Uv_Qf(pGwmMx(FGq`&`Ppp z`UwuW>6{5VzQMT|bS?Gum*HNP%kX?g^auh;-ZFgFG3Gjgcz{r=D_B#8bby*4s9irs z-LJ#He=Hn_jnfN}WG~%(gjqv-fCvW(uMuG)*+tR>Sxys=TVxr4^8|hYZ31o!XpcI` p_s)4TLpE!mKIktaZ~(z|2$%CK#0$W)#H?U$IHV~n{kt}w@IN{HCpG{8 literal 0 HcmV?d00001 diff --git a/regression/strings/RegexMatches01/RegexMatches01.java b/regression/strings/RegexMatches01/RegexMatches01.java new file mode 100644 index 00000000000..79e05c1432d --- /dev/null +++ b/regression/strings/RegexMatches01/RegexMatches01.java @@ -0,0 +1,25 @@ +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class RegexMatches01 +{ + public static void main(String[] args) + { + Pattern expression = + Pattern.compile("W.*\\d[0-35-9]-\\d\\d-\\d\\d"); + + String string1 = "XXXX's Birthday is 05-12-75\n" + + "YYYY's Birthday is 11-04-68\n" + + "ZZZZ's Birthday is 04-28-73\n" + + "WWWW's Birthday is 12-17-77"; + + Matcher matcher = expression.matcher(string1); + + while (matcher.find()) + { + System.out.println(matcher.group()); + String tmp=matcher.group(); + assert tmp.equals("WWWW's Birthday is 12-17-77"); + } + } +} diff --git a/regression/strings/RegexMatches01/test.desc b/regression/strings/RegexMatches01/test.desc new file mode 100644 index 00000000000..45cc542b352 --- /dev/null +++ b/regression/strings/RegexMatches01/test.desc @@ -0,0 +1,8 @@ +FUTURE +RegexMatches01.class +--string-refine --unwind 100 +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/strings/RegexMatches02/RegexMatches02.class b/regression/strings/RegexMatches02/RegexMatches02.class new file mode 100644 index 0000000000000000000000000000000000000000..d696c5eb047587506e9d98de3ecc4d09b9b53ef4 GIT binary patch literal 1273 zcmZ`&SyK~15dJ0yn=A_nfp92jP=s)74z6&?4PJnhSR#iHOESV@lEvMPCI7=0`2#$Q zRl(9KefP~jg!XJW!r?s3^h|eu{q-@wPrm;I(2oTfHE8wWo{alw^WlLw+hueh>PIKK zgw!pg2dWhm2~QO~!vsU{!sq$cE>GK3DCenQ z>)E&|su^F_Y@3_Zr!wPGlWs6B)t*91X(PAiG)0Zx(B0D0^(fQ_Dd+T$F#5_pXLdAm zg}*QGe43ATUh_W{WU9fN%lhG?L@!g=(-k47|+ zEKEPa1uvb`A=fv!7eb!J?w%sNOKK4npAkEPM3S!vzc@xbN01K?Zt{dGi% Date: Wed, 22 Feb 2017 14:13:08 +0000 Subject: [PATCH 002/699] =?UTF-8?q?=C2=A0added=20test=20cases=20related=20?= =?UTF-8?q?to=20string=20methods=20replaceFirst,=20replaceAll=20and=20spli?= =?UTF-8?q?t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucas Cordeiro --- .../RegexSubstitution01.class | Bin 0 -> 2003 bytes .../RegexSubstitution01.java | 39 ++++++++++++++++++ .../strings/RegexSubstitution01/test.desc | 8 ++++ .../RegexSubstitution02.class | Bin 0 -> 1739 bytes .../RegexSubstitution02.java | 32 ++++++++++++++ .../strings/RegexSubstitution02/test.desc | 8 ++++ .../RegexSubstitution03.class | Bin 0 -> 1684 bytes .../RegexSubstitution03.java | 33 +++++++++++++++ .../strings/RegexSubstitution03/test.desc | 8 ++++ 9 files changed, 128 insertions(+) create mode 100644 regression/strings/RegexSubstitution01/RegexSubstitution01.class create mode 100644 regression/strings/RegexSubstitution01/RegexSubstitution01.java create mode 100644 regression/strings/RegexSubstitution01/test.desc create mode 100644 regression/strings/RegexSubstitution02/RegexSubstitution02.class create mode 100644 regression/strings/RegexSubstitution02/RegexSubstitution02.java create mode 100644 regression/strings/RegexSubstitution02/test.desc create mode 100644 regression/strings/RegexSubstitution03/RegexSubstitution03.class create mode 100644 regression/strings/RegexSubstitution03/RegexSubstitution03.java create mode 100644 regression/strings/RegexSubstitution03/test.desc diff --git a/regression/strings/RegexSubstitution01/RegexSubstitution01.class b/regression/strings/RegexSubstitution01/RegexSubstitution01.class new file mode 100644 index 0000000000000000000000000000000000000000..fe4106df4e88e5371dab6ade809873b87cf42302 GIT binary patch literal 2003 zcmZ`(NmCm~6#g1XOe2pC9u_OMu?Ml3MOa25i4BAxvt?m%5HVp1&PZy=;E_h289}(@ zl&YNa2ROP?rw5wBbFD z_c=b`xXp1VhzU%#pdV8lAIgtu1s??wl&Bewcnj`gmSaxAd=Lv*7@6?Pfg`wZ6=j%V6gcg}Q; zq$Sb}Y>T0J%FLSHG=pz&=stsg)=mqC)+IA5R`QvoaMmT56dA+JGIR}YFC7?%M$|I0 z`_Y8wnA!bF`S5(gGg1$ija(70;DLg#8TeGnD%%ex?7Wi_3#POdS`+)?+eAL;dZw3` zZrvKYDebBl!Z3q6XYTFYwemtA9;VN0@w{he49`sI>%#T)S;H0jqR0w|WH!0gv_mMi zOSCEsBvstNV7-;y-CY$aP|Ts4_wh6-OD|PLkCpvs+KE#Ph)40o!6vzKz1Z}l!z zW^i+s>FI{2r|e9|a3^#X7Bb|KzT*z7$ih~TQ}GCn3Rf!n&T>^HRZ@B{lR}3qGefYx z(CrNxM}emzkHb?bFS$sa-=JT~W;v;G%VM}ac($d_N`}sgXnMq>ykWTvo%J?K<(?d( z@v3Wr#IfrMN`lYMQ*fOnbEX}=M>FJ+yTZs!lE1~SIV~ohoCNJLOx5$0Vw|jxutNP7 z>uNdf1=Eok4iwG4;eFYv9O^)^!VEVWunyJJmfuw3rHQtpamO)^DK*@)OKNGS{?Tb) z>lX@xQuNHC(Qd7c(X2&Vj5<9nT+ip8`@$#gg6}E*QTCr`kgIQZhZUMUaz~ok; z{}KA?rjyYb7=8}+iv%J<|IJ0A4=otQO}Z15y#R-w&al?Br1_RdG`|)opn2&jloND} zXuN=y6P)`E!OiD5_eVriwezH3eu@iPtN$h1Hhqyq0T(wSnnutKDQ_>yN3;&Dldwg# zly^12`=+~_A47|1m$Xm;?<{}sV^98jRbr25mrt`xBUcKz8qvB7xVA!{qc3p10KJIs z8ui7ro;P1m7+s_Om=>|GQPtV{6OcARG^=59X~_IGb-jwgz*=8@d|y6qo4JVwJ0%M z1^)*F3U1NwHP+bQXzzNBF$H6xP>8r=)q;-~D+^rI`U@C1f#QDxzwa58n$wlyOTz&) NsWY-g-Yv#7{y%!!^?LvS literal 0 HcmV?d00001 diff --git a/regression/strings/RegexSubstitution01/RegexSubstitution01.java b/regression/strings/RegexSubstitution01/RegexSubstitution01.java new file mode 100644 index 00000000000..06b9e7aaa10 --- /dev/null +++ b/regression/strings/RegexSubstitution01/RegexSubstitution01.java @@ -0,0 +1,39 @@ +import java.util.Arrays; + +public class RegexSubstitution01 +{ + public static void main(String[] args) + { + String firstString = "DiffBlue ***"; + String secondString = "Automatic Test Case Generation"; + + firstString = firstString.replaceAll("\\*", "^"); + + assert firstString.equals("DiffBlue ^^^"); + + secondString = secondString.replaceAll("Automatic", "Automated"); + + System.out.printf( + "\"Automatic\" substituted for \"Automated\": %s\n", secondString); + secondString.equals("Automated Test Case Generation"); + + System.out.printf("Every word replaced by \"word\": %s\n\n", + firstString.replaceAll("\\w+", "word")); + + System.out.printf("Original String 2: %s\n", secondString); + secondString.equals("Automated Test Case Generation"); + + for (int i = 0; i < 3; i++) + secondString = secondString.replaceFirst("\\A", "automated"); + + assert secondString.equals("automatedautomatedautomatedAutomated Test Case Generation"); + + System.out.print("String split at commas: "); + String[] results = secondString.split(" \\s*"); + System.out.println(Arrays.toString(results)); + assert results[0].equals("automatedautomatedautomatedAutomated"); + assert results[1].equals("Test"); + assert results[2].equals("Case"); + assert results[3].equals("Generation"); + } +} diff --git a/regression/strings/RegexSubstitution01/test.desc b/regression/strings/RegexSubstitution01/test.desc new file mode 100644 index 00000000000..bc7ed3648f3 --- /dev/null +++ b/regression/strings/RegexSubstitution01/test.desc @@ -0,0 +1,8 @@ +FUTURE +RegexSubstitution01.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/strings/RegexSubstitution02/RegexSubstitution02.class b/regression/strings/RegexSubstitution02/RegexSubstitution02.class new file mode 100644 index 0000000000000000000000000000000000000000..834c403b3b2d7d0856df177aaeb7f199af9ec69e GIT binary patch literal 1739 zcmZux&sQ5&6#gEQFpptc=pdL{pwkpAgwRk#t$;|%k5=VJZBT?_?Id}LLnoOyGoi9^ zrEB*ryQwa%=cJzYsC)kz_a0C6zDYtra?YH2Z|?o>z2E)jzW3*=7rz6TK}kb5rZ{eJ zOmn=&F{9yayu$IULhhgps}74sV2#{$O((!0o!=D5YN#Iek=!m%pNw>j=e*oPb+ z$?uOftYKYRHo9P9ljE+6Pc#f;O2s`58Ei51jaa@fyufzL{<7^`Sx4j<*e*loyj`|~ z1qNko{4<8glA9L{J!^JZY*b5G;cZDUIZBpYW*8W|zqW53SSiOU7gL$Qv&+Rf8F(%e zSh+{*Rwcx%_*4a1`Fzf4HtU1Gi)acFx=qeqb(HzA$f#vhc{}60MFsLa_%_R>w9zXXrYPXzfK_ z#g2|$+-FF}j{$MhZ}Jd%v*3DW(N+j;|n}!aiiFF+;n`2 zhYVL&4up4TK6bsl>4}PC*%y~h(IwX~7co1R^?%a&u-Wj3c9WIFcJ z)Ra}1MC5f?vg23-#}HgY=RxXLhk zoUYBLA(b4NSWAd>bD~x}&-G}=+Wb=$`#K)MIi+BoC)x@tK-l|PxM8AJzBZ}h!tdp@y@hIRi3uPYaxw`lmE8Lpj7*Yuy{)vz@Mp~L2+ z(w=7>5*Hr0b+^oOGN{R`ov>=i%%M})(;9{)hb|bJ*}U*=PvnnhgKmYON)EbRc5#L7 zr*66rS#L~E9qkk_dEn{&CVdUj%4m%yo`d}?fw)HR&d{i!3u73kJwe$BI3ncx$>>-! zl=TTCVnl1`TuU0N!D+Mp3|)p6`3>DWN-|S}zMVAA)o^}W+I#Bu38UAzK-kbN?M55C zvM|*71V+;6GhVBqfBid!J^lADi5{ro^`sH2;o=5;PX3BFYPj?agGU&cRHls~s&<6# zml)o8j>~_@b~?g#Hqb|Vm3rsYnuZ?eh~Yf7){7|^SS0^4t#{Cm9SqNdH8QH6h literal 0 HcmV?d00001 diff --git a/regression/strings/RegexSubstitution02/RegexSubstitution02.java b/regression/strings/RegexSubstitution02/RegexSubstitution02.java new file mode 100644 index 00000000000..476c0921553 --- /dev/null +++ b/regression/strings/RegexSubstitution02/RegexSubstitution02.java @@ -0,0 +1,32 @@ +import java.util.Arrays; + +public class RegexSubstitution02 +{ + public static void main(String[] args) + { + String firstString = "DiffBlue ***"; + String secondString = "Automatic Test Case Generation"; + + firstString = firstString.replaceAll("\\*", "^"); + + secondString = secondString.replaceAll("Automatic", "Automated"); + + System.out.printf( + "\"Automatic\" substituted for \"Automated\": %s\n", secondString); + secondString.equals("Automated Test Case Generation"); + + System.out.printf("Every word replaced by \"word\": %s\n\n", + firstString.replaceAll("\\w+", "word")); + + System.out.printf("Original String 2: %s\n", secondString); + secondString.equals("Automated Test Case Generation"); + + for (int i = 0; i < 3; i++) + secondString = secondString.replaceFirst("\\A", "automated"); + + System.out.print("String split at commas: "); + String[] results = secondString.split(" \\s*"); + System.out.println(Arrays.toString(results)); + assert results[0].equals("automatedautomatedautomatedaAutomated"); + } +} diff --git a/regression/strings/RegexSubstitution02/test.desc b/regression/strings/RegexSubstitution02/test.desc new file mode 100644 index 00000000000..eb2c03599a1 --- /dev/null +++ b/regression/strings/RegexSubstitution02/test.desc @@ -0,0 +1,8 @@ +FUTURE +RegexSubstitution02.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/RegexSubstitution03/RegexSubstitution03.class b/regression/strings/RegexSubstitution03/RegexSubstitution03.class new file mode 100644 index 0000000000000000000000000000000000000000..fa382774918546a8738294bd1b81a64513954537 GIT binary patch literal 1684 zcmZ`(Npl-T6#m*Hds>r8tc>kMB-oxfnw`$~&USz}6UgChUqG zOfo2=v4;$yX}2gCdNX!KEL6*R;VnxrDaw{zVK_Isp4qmZSV_mKY$bDnXIHjT^5W@S zU=iT6)W0A`8$psm{wpG+;Z9S$4wod!Xm5Y zh9B3FM?nSM5h&@{l8U|)N~hv89X7U)kZw3&(3%9&j>B+o^my+am&A^Xs7=M^Rm<@i z20CptQk#lVA9o}?x910k0bOXAv)$waYSw@P6IMAzRO%HvDkeWW5>#TC==9TI zlj>~!mh1nqt~Ytl*`7~9bl1)PC;FyUIX&I=N-$hM!E3D3ZSzixFHMh=OnaWSN2%d~ z+fYk8otKWr+BvxlYCSTC#;CX5veOPd7t~cn;oF`l9?lBQcu*w;y%lS?M2}a5UN;tr z%88?$0wyPz{@3UW(}A2p@t3+QhtQm4y%=8X|5Yx N`jo81je68K{{_$BnAQLQ literal 0 HcmV?d00001 diff --git a/regression/strings/RegexSubstitution03/RegexSubstitution03.java b/regression/strings/RegexSubstitution03/RegexSubstitution03.java new file mode 100644 index 00000000000..9ea91639e2c --- /dev/null +++ b/regression/strings/RegexSubstitution03/RegexSubstitution03.java @@ -0,0 +1,33 @@ +import java.util.Arrays; + +public class RegexSubstitution03 +{ + public static void main(String[] args) + { + String firstString = "DiffBlue ***"; + String secondString = "Automatic Test Case Generation"; + + firstString = firstString.replaceAll("\\*", "^"); + + assert firstString.equals("DiffBlue ^^^"); + + secondString = secondString.replaceAll("Automatic", "Automated"); + + System.out.printf( + "\"Automatic\" substituted for \"Automated\": %s\n", secondString); + secondString.equals("Automated Test Case Generation"); + + System.out.printf("Every word replaced by \"word\": %s\n\n", + firstString.replaceAll("\\w+", "word")); + + System.out.printf("Original String 2: %s\n", secondString); + secondString.equals("Automated Test Case Generation"); + + for (int i = 0; i < 3; i++) + secondString = secondString.replaceFirst("\\A", "automated"); + + System.out.print("String split at commas: "); + String[] results = secondString.split(" \\s*"); + System.out.println(Arrays.toString(results)); + } +} diff --git a/regression/strings/RegexSubstitution03/test.desc b/regression/strings/RegexSubstitution03/test.desc new file mode 100644 index 00000000000..20da1478b1a --- /dev/null +++ b/regression/strings/RegexSubstitution03/test.desc @@ -0,0 +1,8 @@ +FUTURE +RegexSubstitution03.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring From 9e6ea68c07e6d02c1d2d77d446e16a2fc106d950 Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Wed, 22 Feb 2017 14:14:59 +0000 Subject: [PATCH 003/699] =?UTF-8?q?=C2=A0added=20character=20static=20meth?= =?UTF-8?q?ods=20for=20testing=20characters=20and=20converting=20case?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucas Cordeiro --- .../StaticCharMethods01.class | Bin 0 -> 1067 bytes .../StaticCharMethods01.java | 16 +++++++++ .../strings/StaticCharMethods01/test.desc | 8 +++++ .../StaticCharMethods02.class | Bin 0 -> 644 bytes .../StaticCharMethods02.java | 8 +++++ .../strings/StaticCharMethods02/test.desc | 8 +++++ .../StaticCharMethods03.class | Bin 0 -> 614 bytes .../StaticCharMethods03.java | 8 +++++ .../strings/StaticCharMethods03/test.desc | 8 +++++ .../StaticCharMethods04.class | Bin 0 -> 614 bytes .../StaticCharMethods04.java | 8 +++++ .../strings/StaticCharMethods04/test.desc | 8 +++++ .../StaticCharMethods05.class | Bin 0 -> 1522 bytes .../StaticCharMethods05.java | 33 ++++++++++++++++++ .../strings/StaticCharMethods05/test.desc | 8 +++++ .../StaticCharMethods06.class | Bin 0 -> 917 bytes .../StaticCharMethods06.java | 19 ++++++++++ .../strings/StaticCharMethods06/test.desc | 8 +++++ 18 files changed, 140 insertions(+) create mode 100644 regression/strings/StaticCharMethods01/StaticCharMethods01.class create mode 100644 regression/strings/StaticCharMethods01/StaticCharMethods01.java create mode 100644 regression/strings/StaticCharMethods01/test.desc create mode 100644 regression/strings/StaticCharMethods02/StaticCharMethods02.class create mode 100644 regression/strings/StaticCharMethods02/StaticCharMethods02.java create mode 100644 regression/strings/StaticCharMethods02/test.desc create mode 100644 regression/strings/StaticCharMethods03/StaticCharMethods03.class create mode 100644 regression/strings/StaticCharMethods03/StaticCharMethods03.java create mode 100644 regression/strings/StaticCharMethods03/test.desc create mode 100644 regression/strings/StaticCharMethods04/StaticCharMethods04.class create mode 100644 regression/strings/StaticCharMethods04/StaticCharMethods04.java create mode 100644 regression/strings/StaticCharMethods04/test.desc create mode 100644 regression/strings/StaticCharMethods05/StaticCharMethods05.class create mode 100644 regression/strings/StaticCharMethods05/StaticCharMethods05.java create mode 100644 regression/strings/StaticCharMethods05/test.desc create mode 100644 regression/strings/StaticCharMethods06/StaticCharMethods06.class create mode 100644 regression/strings/StaticCharMethods06/StaticCharMethods06.java create mode 100644 regression/strings/StaticCharMethods06/test.desc diff --git a/regression/strings/StaticCharMethods01/StaticCharMethods01.class b/regression/strings/StaticCharMethods01/StaticCharMethods01.class new file mode 100644 index 0000000000000000000000000000000000000000..9236c2521e11657d1630d0ed02aee55588a90dac GIT binary patch literal 1067 zcmZuwO-~b16g{sUI_-3zP}*8SP!zSG@+E$@B3d-jfS6Q`;%eGH;9;2|ZwB4_CyZ=d zx^bf>Vl>f}F8oc#c<+SLrs+)P%)95^&+}&f{QLF;z&sW$3}7^Y6pmXsfiV*&Ef^SO z;}pX+Q%2mOF zK(sLNM8GI}bt#ZqR<3-oyIqy~5j)eywxe8uT;cihmh;k?ZaD77bS2Qr-6(QkZzXVQ zFIJqL1OIrb);P#)RlHqYlXn&8$&+88YUNEwugGB2tNSyvQ=HL823Z?v44Rm+F^f5J zZk4*#?Ej9|p0;rjb2dpuaEakE!xe_B4A&U0qiCaqB8}grsEHdk7I0Ibzg1VsTKV!T&UmmQxZBkS?b&Y=}}Z5FptCYQi#3rMwf-=Kr1W2;MFX<0v1 zkp$PmM}-w2)zZpdnWfGKC&Z@5XM51WI-NBX-%$T z2obu0-_g=1MD{Q^{1s8-9g^Q+JljXl&yYg3EC>1%72XN`ojP9aI_9R4SMkbefULk4v}{s5`U2w wnM^iASDqq<4<(%swF3sysW0f?gK4~n5&euvt7KDNPDO?7MLvXMVMinX0ZQ)T{r~^~ literal 0 HcmV?d00001 diff --git a/regression/strings/StaticCharMethods01/StaticCharMethods01.java b/regression/strings/StaticCharMethods01/StaticCharMethods01.java new file mode 100644 index 00000000000..d8e2f9d261b --- /dev/null +++ b/regression/strings/StaticCharMethods01/StaticCharMethods01.java @@ -0,0 +1,16 @@ +public class StaticCharMethods01 +{ + public static void main(String[] args) + { + char c = 0; + assert Character.isDefined(c)==true; + assert Character.isDigit(c)==false; + assert Character.isJavaIdentifierStart(c)==false; + assert Character.isJavaIdentifierPart(c)==true; + assert Character.isLetter(c)==false; + assert Character.isLetterOrDigit(c)==false; + assert Character.isLowerCase(c)==false; + assert Character.isUpperCase(c)==false; + assert Character.toUpperCase(c)==Character.toLowerCase(c); + } +} diff --git a/regression/strings/StaticCharMethods01/test.desc b/regression/strings/StaticCharMethods01/test.desc new file mode 100644 index 00000000000..4b633e92bcf --- /dev/null +++ b/regression/strings/StaticCharMethods01/test.desc @@ -0,0 +1,8 @@ +FUTURE +StaticCharMethods01.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/strings/StaticCharMethods02/StaticCharMethods02.class b/regression/strings/StaticCharMethods02/StaticCharMethods02.class new file mode 100644 index 0000000000000000000000000000000000000000..78ad3dbdc778f1bd3920af2b50b3ca56d49e9763 GIT binary patch literal 644 zcmZvZ&rcIU6vw~QZ98SV(DK7tDWG80;z11IW@9jmghPQt!NhW!?oP^J*==U0_`h)S z=2=OAXrg!jCSrWEq0|G}?99A3?|t6)z4`O^$1eaIc;R9Kl?iY>bWz14yUcUcT;x#U zSa7k3C631ovvrXqQX3UV$(Bk)w=Y8m)?vsuRiw;Y2B)$5fg$V1p=2nvR3!I?r(LNJ zY%pD%3KcO_8b_@YaVFOKBI>QRjaE_bjZK_v8xefk6@%OOLNn;!lHGPZ)PdYqmQ$rT zqXPd}=v`@!<1l%>{>lY!!lMpJjDuSjO)D{HSu2SSW{c~z&Pq2p5Zw| zd7QZ4J&}Q-gt5yi5P^||DVq3jFp%08iS4xEullL86@MN%OaCSIX_hpJP$o*t@J^G} zGNcO{WQXK)dK-Y1tF|RNIbgO!TBpcbq@B^8dwB)+%?6@GYd&={N-blW&Ng%h8Tx<) zr}-V3b5v^AaOlr|LGdSYAFq)AZ3&r_Fhzw3OI98=5-~#-QEyOVC}8$Zz(!gLn4aO6 cD4c_5zar~gATvgd#8?CYy-h25F0J(7A5^q|OaK4? literal 0 HcmV?d00001 diff --git a/regression/strings/StaticCharMethods02/StaticCharMethods02.java b/regression/strings/StaticCharMethods02/StaticCharMethods02.java new file mode 100644 index 00000000000..658186e9603 --- /dev/null +++ b/regression/strings/StaticCharMethods02/StaticCharMethods02.java @@ -0,0 +1,8 @@ +public class StaticCharMethods02 +{ + public static void main(String[] args) + { + char c = 0; + assert Character.toUpperCase(c)!=Character.toLowerCase(c); + } +} diff --git a/regression/strings/StaticCharMethods02/test.desc b/regression/strings/StaticCharMethods02/test.desc new file mode 100644 index 00000000000..496814588a7 --- /dev/null +++ b/regression/strings/StaticCharMethods02/test.desc @@ -0,0 +1,8 @@ +FUTURE +StaticCharMethods02.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StaticCharMethods03/StaticCharMethods03.class b/regression/strings/StaticCharMethods03/StaticCharMethods03.class new file mode 100644 index 0000000000000000000000000000000000000000..264331b2fbec8488bb351cb190da21a20bc14000 GIT binary patch literal 614 zcmZuuT`vPc6g|^jyX{(9t&jTtd?*hp;Y}l?<;llGMS`d4?$D{)mD#QT!XNOA1R>$w zZxV5*K|RPMGxyG%d(OFc-ansT0jyxoK@tNgSQvCLguIPm2POt=j5rv@n2m9U+#HW0 zp<)>ZQAI|)))YPiJ7Ta(GLZ2agHf12U@*&}FBsC>G7!71^O{im8cYx8Tm}q-h2!l8 zzvRUx4^E5KSjpgYRTuVDWA2^p@QZJJvg9?tnVo9bQl8k7nkP@VSbF6;S34rEhkmrQ zyr>ynbi;L#f@5RC#U!Q(+>zS&@xQ55sHmfVcx+6&n87SVrc=0AYX~oRg{CULqaQ{Eqlh=H9lI4v1Vz0F`XHjWwWb`lAOQb)$(V0hIR>d1iU;fl+c zVWDx>x#ZvY=77iNn?0>$e7@ONJ^GpQX_W2&ZM(zTm1W z^hFY-pPC=lsO3CVwN(Jd_q7yVQ%c+%xr+!Ip+@UHC+1#Z0i=eiPWePBSC`xj;Xhj HIlXxS5x96E literal 0 HcmV?d00001 diff --git a/regression/strings/StaticCharMethods04/StaticCharMethods04.java b/regression/strings/StaticCharMethods04/StaticCharMethods04.java new file mode 100644 index 00000000000..70fa2be2f36 --- /dev/null +++ b/regression/strings/StaticCharMethods04/StaticCharMethods04.java @@ -0,0 +1,8 @@ +public class StaticCharMethods04 +{ + public static void main(String[] args) + { + char c = 0; + assert Character.isLetter(c)==true; + } +} diff --git a/regression/strings/StaticCharMethods04/test.desc b/regression/strings/StaticCharMethods04/test.desc new file mode 100644 index 00000000000..93eebbae1da --- /dev/null +++ b/regression/strings/StaticCharMethods04/test.desc @@ -0,0 +1,8 @@ +FUTURE +StaticCharMethods04.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StaticCharMethods05/StaticCharMethods05.class b/regression/strings/StaticCharMethods05/StaticCharMethods05.class new file mode 100644 index 0000000000000000000000000000000000000000..c58f3d328afb757005812bcbc2145c7350cb5c38 GIT binary patch literal 1522 zcmZuxOLH4V5dKD5?a1r3Ez6c45D^9PketK{kO=ULIBSO}v111XCw5+}rHQkNyz5%6 z4EzHQ965z5C{7&U5~oUbB^9{ym#9k7y^<|C<-_*OPIrIZ{dLd$`}Wn}04~Bd(1X(w zXS$F@&OiiXEY5ae80RF;8<057y74&j1}@;^I6jg1)F9tWEDC)1Ssb6U+ZP5VFd4@b zYo-m%;7f_i24-=DstAZR0e#AGonS^Fn$4{UXqHz|0(}dP zt8Uge*Oh;pjY+X-JFdV`_TIu%d)v-eZFeJI3Vg@im}JMEQec;#E!tb5JryMopDI^d z;6}--`(<_2VW<%@4V<#|#P%0e@WiXsE?gRCP!sRtm_UCRpdL8Ye5q`^uJR=;6LXkn zgR3UK!Zj14c#ojkxyFd=cn!~zxtj$59)O@uTR znZV1GDIL2^))SdiHA5iLhF)5Ks>*@HO%qF4HgOAIn<(M7Kyn|y?QP;4tVrB3aTlu{ zfetJ z<|NURJyOB_lCJtbD7rz|_##QKPWv{{GIh2MG!T+O_#MZDvBgGJPM{U&-Kl8$g{R!^ zkY5^%$DTjO4H1ZCi^ZHpP}_F3u9hBi&Q`8t#17o396gLjHd9B0>zvDG!zNoehtnn; zjcXSe%ytH9&GKQA!}+Gb+`L(G(XwH-v9N!fy;aN+dCiFp%OpzGhVuEQ6g%Nt=M=rK zJy=$it|ggPRL${KJFm2&=$@%5SwP9Z_VsLe~!WQFNml0-_iXV za&;H+f6{-F&yVy)=;KhMt^I=?bR~@jy4k;=@t>)^LCxRQ1izuMkIr8GO^jr;fq{a~Cxa~=0 && choice<3; + + switch (choice) + { + case 1: // convert digit to character + System.out.println("Enter a digit:"); + int digit = scanner.nextInt(); + System.out.printf("Convert digit to character: %s\n", + Character.forDigit(digit, radix)); + char tmp=Character.forDigit(digit, radix); + assert tmp=='t'; + break; + + case 2: // convert character to digit + System.out.println("Enter a character:"); + char character = scanner.next().charAt(0); + System.out.printf("Convert character to digit: %s\n", + Character.digit(character, radix)); + break; + } + } +} diff --git a/regression/strings/StaticCharMethods05/test.desc b/regression/strings/StaticCharMethods05/test.desc new file mode 100644 index 00000000000..e009650a853 --- /dev/null +++ b/regression/strings/StaticCharMethods05/test.desc @@ -0,0 +1,8 @@ +FUTURE +StaticCharMethods05.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StaticCharMethods06/StaticCharMethods06.class b/regression/strings/StaticCharMethods06/StaticCharMethods06.class new file mode 100644 index 0000000000000000000000000000000000000000..10f416854e6eeca224d6bab498a22308a30ec85c GIT binary patch literal 917 zcmZuwT~8B16g|_g-EOz^1ByiiilVfD6cDPW#7L?>wPI3ZB0f#GBP?!rad%7fr^p}R zSxk!2MBn{S8t-g@wh75*_U_zs&pmVQ?4N%>egW9TV+~16Yq*6Oxy;5fhk}ZE4YzSe z#X=kj+*NQ-Lmblz7Bv)6Qn17@zQ8?CxW4Jw-ZRtVElac+*d9Y{+q6yp2}8J8dczQ@ zIc>p^s++cW+3mE1`&xo2(cz}eFj;(8Kjg=}Y;k+P-1J@3-ml8SWYg!yhXy|i@Cue0 z)NRAMAlI5s*EPfoQ&Qy#>YGOGfV&OhA2@Aqt+Fafb)=D@QXMO}uVWQu1#3FivB5B5 ztQWZ5E*KjH?uvr=*yWa{;DJuQY!T;Z+IIX4h>kI&C_fOrbLqr$*L7U-<{CK)DmotG z5kq=VxZ64uhED~9EqMlR_=0GZV{UcD?tAK0td)jLy24b+?LfE3kSh)$`oz@|jbo@? z^RwrR4h_cXQqx=?Z#v~y1&4GjNZ|ubFi-xh;dqD!6u^%Ie{F- z68Z@tDh4X)o$mY%}; Rcu5pRNPjAiI2H82`5(=T#Owe7 literal 0 HcmV?d00001 diff --git a/regression/strings/StaticCharMethods06/StaticCharMethods06.java b/regression/strings/StaticCharMethods06/StaticCharMethods06.java new file mode 100644 index 00000000000..ca8ff1604ac --- /dev/null +++ b/regression/strings/StaticCharMethods06/StaticCharMethods06.java @@ -0,0 +1,19 @@ +public class StaticCharMethods06 +{ + public static void main(String[] args) + { + Character c1 = 'A'; + Character c2 = 'A'; + + if (c1.equals(c2)) + { + System.out.println("c1 and c2 are equal\n"); + assert true; + } + else + { + System.out.println("c1 and c2 are not equal\n"); + assert false; + } + } +} diff --git a/regression/strings/StaticCharMethods06/test.desc b/regression/strings/StaticCharMethods06/test.desc new file mode 100644 index 00000000000..6f351b2c7cf --- /dev/null +++ b/regression/strings/StaticCharMethods06/test.desc @@ -0,0 +1,8 @@ +FUTURE +StaticCharMethods06.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring From 0b056151819f54d99447251e4f4f3d2392b3ec30 Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Wed, 22 Feb 2017 14:16:01 +0000 Subject: [PATCH 004/699] =?UTF-8?q?=C2=A0added=20test=20cases=20related=20?= =?UTF-8?q?to=20sringBuilder=20append=20methods?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucas Cordeiro --- .../StringBuilderAppend01.class | Bin 0 -> 1860 bytes .../StringBuilderAppend01.java | 43 ++++++++++++++++++ .../strings/StringBuilderAppend01/test.desc | 8 ++++ .../StringBuilderAppend02.class | Bin 0 -> 1861 bytes .../StringBuilderAppend02.java | 43 ++++++++++++++++++ .../strings/StringBuilderAppend02/test.desc | 8 ++++ 6 files changed, 102 insertions(+) create mode 100644 regression/strings/StringBuilderAppend01/StringBuilderAppend01.class create mode 100644 regression/strings/StringBuilderAppend01/StringBuilderAppend01.java create mode 100644 regression/strings/StringBuilderAppend01/test.desc create mode 100644 regression/strings/StringBuilderAppend02/StringBuilderAppend02.class create mode 100644 regression/strings/StringBuilderAppend02/StringBuilderAppend02.java create mode 100644 regression/strings/StringBuilderAppend02/test.desc diff --git a/regression/strings/StringBuilderAppend01/StringBuilderAppend01.class b/regression/strings/StringBuilderAppend01/StringBuilderAppend01.class new file mode 100644 index 0000000000000000000000000000000000000000..b6202d6fc9ac4595ee3ca4131f90ffa63a33fd5a GIT binary patch literal 1860 zcmah}&vV;E7=3HYT3MD8;lxgyCQX1EoVNK@r%9WHlGJG+B}ogh+uEUkY|BN(l~dWy zfg=Yl%)o_HF1>Vyfdey8MqwzF87?pk!weTLTsZW`{{Va|$4N*t#HGHE)qA`9 z^WWb*0x*fPil>oMFsa~dfZq5rp~sNshX8qg{Q>dREm}3BP%%pkEYBd%S+-Tbz~D~~Ut^Hc)so53xnkMoTH{W^bTT5D0(T6{W{4#> zR&E{bP>qhaNRb$i3=eR=Sa$Mzjl|Gh1nJZRy2U6Fo4X0=> zS)y!Tv&6-QRVkUy!se!Fm&PYX#Sj`!AVED#R=HfLG{hY0X06W9b9e%~y%|CkqgEd( zG|FYu5#3+Yu#OCaFJTLo6>v?!bpba7ZMbfA12#fxc*epr1Y@}&` z7_-Aq^x5@b_E3Ing|x{ZNN%Lt)f=Sv@^ZV3{$##=xNZIZ9-AM-Mrf{?V{OMVWnPeS=gO?vOIYpQyHUDJLGQ5Jlgi1`^zRxOOi5UC9`HZW@&E$ z(uS@#C_o28o=&tux&fy5iXB1B4<Ii3z3ND31#mkqeCi*Vd9j^ zeuaciYNd#8CE{PzwQmDCzrK~tNxGTM1#~BylXWYb<9a!pQv}mxy-3J)gHX}yghB7U zs#l4JbUV8yO-XuwDxmWzxf{|nkI3hO-QefdhY02(>JCCPnxH$-X2S9CDHq{Lhl|eB zbbDmPh2A87*~L>HjY=*eO%`y`)npXy_E?O&hLKDCP5%`p^?KK(fkoajZhYRnjd36*myVO^CB1j529= z7dqZW1n;2>@1q+ZAc~I=!^h~sHhOUnaok5AKE*M7j($8Kd%nhTd`Bk!fFb-yR{laZ z{zhZ|PA2|AHvUQ8JSLa^!Z7pWBwe5g`-dLF9H%%=bBu6|GR7pIpJUAXk5HC^@x5g* m>G=(kZ_vfiHn{W&B>w~S?SE)%Nr(Xg@M-g6;Y@fsocR|#Be9hL literal 0 HcmV?d00001 diff --git a/regression/strings/StringBuilderAppend01/StringBuilderAppend01.java b/regression/strings/StringBuilderAppend01/StringBuilderAppend01.java new file mode 100644 index 00000000000..26e164c02c9 --- /dev/null +++ b/regression/strings/StringBuilderAppend01/StringBuilderAppend01.java @@ -0,0 +1,43 @@ +public class StringBuilderAppend01 +{ + public static void main(String[] args) + { + Object objectRef = "diffblue"; + String string = "test"; + char[] charArray = {'v', 'e', 'r', 'i', 'f', 'i', 'c', 'a', 't', 'i', 'o', 'n'}; + boolean booleanValue = true; + char characterValue = 'Z'; + int integerValue = 7; + long longValue = 10000000000L; + float floatValue = 2.5f; + double doubleValue = 33.333; + + StringBuilder lastBuffer = new StringBuilder("last buffer"); + StringBuilder buffer = new StringBuilder(); + + buffer.append(objectRef) + .append("%n") + .append(string) + .append("%n") + .append(charArray) + .append("%n") + .append(charArray, 0, 3) + .append("%n") + .append(booleanValue) + .append("%n") + .append(characterValue) + .append("%n") + .append(integerValue) + .append("%n") + .append(longValue) + .append("%n") + .append(floatValue) + .append("%n") + .append(doubleValue) + .append("%n") + .append(lastBuffer); + + String tmp=buffer.toString(); + assert tmp.equals("diffblue%ntest%nverification%nver%ntrue%nZ%n7%n10000000000%n2.5%n33.333%nlast buffer"); + } +} diff --git a/regression/strings/StringBuilderAppend01/test.desc b/regression/strings/StringBuilderAppend01/test.desc new file mode 100644 index 00000000000..f1f89b629be --- /dev/null +++ b/regression/strings/StringBuilderAppend01/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringBuilderAppend01.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/strings/StringBuilderAppend02/StringBuilderAppend02.class b/regression/strings/StringBuilderAppend02/StringBuilderAppend02.class new file mode 100644 index 0000000000000000000000000000000000000000..bf07da6a61302cc8589caf7a84d69ba8c0046853 GIT binary patch literal 1861 zcmah}&vV;E7=3HYT3MD8;W$5>CQX0}oVNMVI8E9ll%!4rDM?yL+|~{SWLqvOuAItt z4jegfVFoUoa_OZr3>=t&G73YX%y5BW7-qO|;liOe{s-V&IZi^FF_!iAN#D2MuHM_- zpa1^m5r7GlR6LE8f(Zp@L-Z!F9(fFDZV-^?=03akXzQo1I3^WLsR-kofRupq3Z_Ln zBVbm*3j!_(cu~NdfO!EI1*8Qm2)Go+02URzq~c{Paa>l>j}*r%DweUrvC7bK!mL&; zw`NzI>VjQ0^JS~Zz;X=otnJvf3k<>J&@~1rT`5`&?aQ`ft=8}4Eq7fcQ{awiI}BaP zjpf_smN{BBom-=8HP?1-&4`ZCwVGLYXT{v~^Es~2xExnGUZsy^P-Y9|-GS7#O5H73 zi?%4++bD6dZkLOeJHNSUImNN@5ix{@6ELV}(Jqzp<+_+d&8pTIx(`oaw>LwiY*uT7 z`Fg2jxuW}P8rHDR5HK9UG6Jp%xGvy^fUJO=fDHk!3%DuZ4GnMNEe+4$S%yq=5{4t@ zU^rWrYnSYTDHQdeDB#vD!!dG(Gi5ku#`b=OGd^RUm;nj_~L|iH(w^%SM_8NFME|Z2E363?EEr zj4?CxM4w#~W)9^ymq?5J{^UlwRlNaLGWV=Fz@y-(NOqT9TC6RkW(MYZdnv zAnoW{odR?+2B*GCHM_7$Q!o z>{m!=r&fvumSe#cUHdka4eDE&tfX6+Y)E%ASy{I;S+18dSw%2i)(eDOHwhKJMi}+-F_fL#NNW!ydYP)}wmp_E|#n&~rTz^^llu z`x3p|=uEW5j(OXW~q8z6 Date: Wed, 22 Feb 2017 14:17:03 +0000 Subject: [PATCH 005/699] =?UTF-8?q?=C2=A0added=20stringBuilder=20methods?= =?UTF-8?q?=20length,=20setLength,=20capacity=20and=20ensureCapacity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucas Cordeiro --- .../StringBuilderCapLen01.class | Bin 0 -> 1092 bytes .../StringBuilderCapLen01.java | 18 ++++++++++++++++++ .../strings/StringBuilderCapLen01/test.desc | 8 ++++++++ .../StringBuilderCapLen02.class | Bin 0 -> 871 bytes .../StringBuilderCapLen02.java | 8 ++++++++ .../strings/StringBuilderCapLen02/test.desc | 8 ++++++++ .../StringBuilderCapLen03.class | Bin 0 -> 725 bytes .../StringBuilderCapLen03.java | 8 ++++++++ .../strings/StringBuilderCapLen03/test.desc | 8 ++++++++ .../StringBuilderCapLen04.class | Bin 0 -> 727 bytes .../StringBuilderCapLen04.java | 8 ++++++++ .../strings/StringBuilderCapLen04/test.desc | 8 ++++++++ 12 files changed, 74 insertions(+) create mode 100644 regression/strings/StringBuilderCapLen01/StringBuilderCapLen01.class create mode 100644 regression/strings/StringBuilderCapLen01/StringBuilderCapLen01.java create mode 100644 regression/strings/StringBuilderCapLen01/test.desc create mode 100644 regression/strings/StringBuilderCapLen02/StringBuilderCapLen02.class create mode 100644 regression/strings/StringBuilderCapLen02/StringBuilderCapLen02.java create mode 100644 regression/strings/StringBuilderCapLen02/test.desc create mode 100644 regression/strings/StringBuilderCapLen03/StringBuilderCapLen03.class create mode 100644 regression/strings/StringBuilderCapLen03/StringBuilderCapLen03.java create mode 100644 regression/strings/StringBuilderCapLen03/test.desc create mode 100644 regression/strings/StringBuilderCapLen04/StringBuilderCapLen04.class create mode 100644 regression/strings/StringBuilderCapLen04/StringBuilderCapLen04.java create mode 100644 regression/strings/StringBuilderCapLen04/test.desc diff --git a/regression/strings/StringBuilderCapLen01/StringBuilderCapLen01.class b/regression/strings/StringBuilderCapLen01/StringBuilderCapLen01.class new file mode 100644 index 0000000000000000000000000000000000000000..caf6da81f4b50a3500f4fec45cf9f42fdcba13d6 GIT binary patch literal 1092 zcmZuwTTc^F5dKbYyKEPFftHIPi&kwxxoEu>5d}?%RTD8r@aeQY)Wv06_d?=dF!2xY z;v>GQNl7HpcmI$t#yDr8v>-2YX6N$F%r~>Y{(k=fpom2cDU2&HR7_|H;am?AI4`xF zh6}i;;F1Ovyp4-Jw0iriq2D?Hjnkd)}Ozhu$r(Bf;tH62kq;)(X{`Q)IxS;qvOW{R$sC5I%< zq=iA_AVV@sUt{z#dZUwjU|(b)21&*OBbCMwhDn#9zbQ3D@8^Al*3#iUM9ND<`mjwTeMAzwMAZmI_9FHNIR$63*|E`K qN*F!js~8Xiq|%8Nk~>f$yNHCpA=;_d=1w9-5z-eW!(%}+Xa50k= zxt4Ur>!{xm{#zxci$0ew!%Fp}b;dvPy2IUGy&d|}?d_|;Y&+!k`&ayYtfvYY^aIY+D*F)USU|7!k%O_eF}A>vMOg*r*K zU!xDt%?oHcG!^uxT@grMbZ1YYuM8u)ppiJnI!#!XhL7dTs)OXkL77pYwMe@)vW#qU zYXtUL39(3PYJA9O5|^+{zLK^nG)8vw0F literal 0 HcmV?d00001 diff --git a/regression/strings/StringBuilderCapLen02/StringBuilderCapLen02.java b/regression/strings/StringBuilderCapLen02/StringBuilderCapLen02.java new file mode 100644 index 00000000000..5397130cde4 --- /dev/null +++ b/regression/strings/StringBuilderCapLen02/StringBuilderCapLen02.java @@ -0,0 +1,8 @@ +public class StringBuilderCapLen02 +{ + public static void main(String[] args) + { + StringBuilder buffer = new StringBuilder("Diffblue is leader in automatic test case generation"); + assert buffer.toString().equals("Diffblue is leader in automatic test case generation"); + } +} diff --git a/regression/strings/StringBuilderCapLen02/test.desc b/regression/strings/StringBuilderCapLen02/test.desc new file mode 100644 index 00000000000..cf2a98acf6d --- /dev/null +++ b/regression/strings/StringBuilderCapLen02/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringBuilderCapLen02.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringBuilderCapLen03/StringBuilderCapLen03.class b/regression/strings/StringBuilderCapLen03/StringBuilderCapLen03.class new file mode 100644 index 0000000000000000000000000000000000000000..a14ea26291a431c2b0a62f01437efa88299aaa90 GIT binary patch literal 725 zcmZuvT~8B16g{_J+b#=~@>NlEi>L(?F`;h~qZUm}>PJ#z0zOT5hdQ{OCA+i!7+!qz zSxsmniN5=rjPcG2G%>u)y)*Zob5G8lUw^*;0MNmviz!@juu{cU7X@6ap@vnPU3YN9 zg=34pix$=#+$7Aei!_yqQL#>URVoIN3<c*iY%=VO)FSF4= zCU0yr7e+#9!czNP?@)XcTanPit-eW=9zL+Z>An%chZo`~?`LI%>P`@yk-PmkO9J^! zS*n$PuqT;{LYZ{MQBUgo+xIN3hZ)Qgmj54d)=TK@s)K_;lu2Kuek27G_)7aCGx10m z75GM`#t%d){h`z{;kQ^@)^!garaj!kZ9;Rx|M=XOr%4hggvCq6Ik@AYjSWJ50(~_& zl!0ML`*KSvk<>%;KDYKcdpbdOBVGra8Ol^8GQ7~h9-52`yo-I_U5%FvP`zoTb5;ad zfB3BPZIvT&EN_lMUu+}h_^jlQ#NYSqD#;E?ZJcXQRhA~VIml<39p%(a71^q_L!6Ii%7eYGuL}0E_JAr!)r}P=6;y08h TWapwRNf`z2k(Iuj&uab!BFvcu literal 0 HcmV?d00001 diff --git a/regression/strings/StringBuilderCapLen03/StringBuilderCapLen03.java b/regression/strings/StringBuilderCapLen03/StringBuilderCapLen03.java new file mode 100644 index 00000000000..86ac16fcdf6 --- /dev/null +++ b/regression/strings/StringBuilderCapLen03/StringBuilderCapLen03.java @@ -0,0 +1,8 @@ +public class StringBuilderCapLen03 +{ + public static void main(String[] args) + { + StringBuilder buffer = new StringBuilder("Diffblue is leader in automatic test case generation"); + assert buffer.length()==51; + } +} diff --git a/regression/strings/StringBuilderCapLen03/test.desc b/regression/strings/StringBuilderCapLen03/test.desc new file mode 100644 index 00000000000..7095d79fe5f --- /dev/null +++ b/regression/strings/StringBuilderCapLen03/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringBuilderCapLen03.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringBuilderCapLen04/StringBuilderCapLen04.class b/regression/strings/StringBuilderCapLen04/StringBuilderCapLen04.class new file mode 100644 index 0000000000000000000000000000000000000000..7350cb80672ee89e07c8972ee8afefd266904144 GIT binary patch literal 727 zcmZuvU279T6g`u#-E6mQntsJZxZp&+BP74nR{pMJ?9?IonL>x{{Ya&wudR)aIoUyriTJthD949owIxaehQ@5$riew>Lwra>$?5d=~NJTu9V z8yN;hq$UV?DuRJfLepEKEbE33AJaZIahIVn;eUGR%f8l$W>~ydoP&ElTG(Q!O`xy) zCn7WiX?tkG?iBBNN|9)o?cjhLgel0Py6*D+7IZ9O1pf#TXZ3WxRL7^Uu4luxm6{|uGd z{wGYG!#Nzo{b_j$InNAXh#Vd Date: Wed, 22 Feb 2017 14:17:56 +0000 Subject: [PATCH 006/699] =?UTF-8?q?=C2=A0added=20stringBuilder=20methods?= =?UTF-8?q?=20charAt,=20setCharAt,=20getChars=20and=20reverse?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucas Cordeiro --- .../StringBuilderChars01.class | Bin 0 -> 1413 bytes .../StringBuilderChars01.java | 28 ++++++++++++++++++ .../strings/StringBuilderChars01/test.desc | 8 +++++ .../StringBuilderChars02.class | Bin 0 -> 797 bytes .../StringBuilderChars02.java | 8 +++++ .../strings/StringBuilderChars02/test.desc | 8 +++++ .../StringBuilderChars03.class | Bin 0 -> 692 bytes .../StringBuilderChars03.java | 8 +++++ .../strings/StringBuilderChars03/test.desc | 8 +++++ .../StringBuilderChars04.class | Bin 0 -> 1018 bytes .../StringBuilderChars04.java | 18 +++++++++++ .../strings/StringBuilderChars04/test.desc | 8 +++++ .../StringBuilderChars05.class | Bin 0 -> 850 bytes .../StringBuilderChars05.java | 10 +++++++ .../strings/StringBuilderChars05/test.desc | 8 +++++ .../StringBuilderChars06.class | Bin 0 -> 856 bytes .../StringBuilderChars06.java | 9 ++++++ .../strings/StringBuilderChars06/test.desc | 8 +++++ 18 files changed, 129 insertions(+) create mode 100644 regression/strings/StringBuilderChars01/StringBuilderChars01.class create mode 100644 regression/strings/StringBuilderChars01/StringBuilderChars01.java create mode 100644 regression/strings/StringBuilderChars01/test.desc create mode 100644 regression/strings/StringBuilderChars02/StringBuilderChars02.class create mode 100644 regression/strings/StringBuilderChars02/StringBuilderChars02.java create mode 100644 regression/strings/StringBuilderChars02/test.desc create mode 100644 regression/strings/StringBuilderChars03/StringBuilderChars03.class create mode 100644 regression/strings/StringBuilderChars03/StringBuilderChars03.java create mode 100644 regression/strings/StringBuilderChars03/test.desc create mode 100644 regression/strings/StringBuilderChars04/StringBuilderChars04.class create mode 100644 regression/strings/StringBuilderChars04/StringBuilderChars04.java create mode 100644 regression/strings/StringBuilderChars04/test.desc create mode 100644 regression/strings/StringBuilderChars05/StringBuilderChars05.class create mode 100644 regression/strings/StringBuilderChars05/StringBuilderChars05.java create mode 100644 regression/strings/StringBuilderChars05/test.desc create mode 100644 regression/strings/StringBuilderChars06/StringBuilderChars06.class create mode 100644 regression/strings/StringBuilderChars06/StringBuilderChars06.java create mode 100644 regression/strings/StringBuilderChars06/test.desc diff --git a/regression/strings/StringBuilderChars01/StringBuilderChars01.class b/regression/strings/StringBuilderChars01/StringBuilderChars01.class new file mode 100644 index 0000000000000000000000000000000000000000..f2645ec7774fe7282656930ac6aaece797a417a8 GIT binary patch literal 1413 zcmZuw-%}G;6#j1Z#|_IOA-F=YDk`=cgP?-Z3Mvpp(gw9AYL%xYx!}@Gg1Z}MeD|?4 zed-I-nRYsz@mZXK8FBETZ=L=N^)GS6b2nhX^00T$J@>okJLfy+{`2w87JyOwXu!f5 zj<4hR#y|{q8@iE})>#7?404<^5XTwm8IsGeT+X-Q0xlXD!KmC`iX$ukm*cp?@vVWY z7~>dc=pJx_K=`3suLaX?;4FBe!oVIg=;Ln94X-mOcKQK>nyXg?LubLQiQA3pg78Zc zOb1oRtuY+2=L^fuGiTUyYD>e#(06M~WAb80F?7m5%{eO(p6cMZ#zAr8<7ID$!YI}o zep$@8GGMBCd8*-h72)TeIDT;c!jOz@q8BNKo-cWJpbUv=cX4sbYl!}WTXjQGkvDFb zID#G%6PV@;rWP07S%$+0mBVr0!~;B}8?8j{EG&z1NIf|~Nru>bj={1I z7C9c)n>55{r~i-H$Fqyn#nXo41z$vMW-*qQBTy#sCn+P<&Zmi8_e5uE;A1|86>KgLOV zU>3bSmgtp}LzV)X7^GB&XIVURjDr2%3id)_FLd^D``?U`m|aI_CZQ)v z^xuN#Oq|(s7EC1^<8njuU;`wC5cCWOJNk@+18};2hf~4z+ax*vH9p p>T|0`qn-d=$?kO=UIkZQLRDTvYo)x~Hc6==W=_cFo{lOS_yi#cGPD2y literal 0 HcmV?d00001 diff --git a/regression/strings/StringBuilderChars01/StringBuilderChars01.java b/regression/strings/StringBuilderChars01/StringBuilderChars01.java new file mode 100644 index 00000000000..10265254980 --- /dev/null +++ b/regression/strings/StringBuilderChars01/StringBuilderChars01.java @@ -0,0 +1,28 @@ +public class StringBuilderChars01 +{ + public static void main(String[] args) + { + StringBuilder buffer = new StringBuilder("DiffBlue Limited"); + + assert buffer.toString().equals("DiffBlue Limited"); + assert buffer.charAt(0)!=buffer.charAt(4); + + char[] charArray = new char[buffer.length()]; + buffer.getChars(0, buffer.length(), charArray, 0); + + int i=0; + for (char character : charArray) + { + System.out.print(character); + assert character==buffer.charAt(i); + ++i; + } + + buffer.setCharAt(0, 'H'); + buffer.setCharAt(6, 'T'); + assert buffer.toString().equals("HiffBlTe Limited"); + + buffer.reverse(); + assert buffer.toString().equals("detimiL eTlBffiH"); + } +} diff --git a/regression/strings/StringBuilderChars01/test.desc b/regression/strings/StringBuilderChars01/test.desc new file mode 100644 index 00000000000..41dfe54abeb --- /dev/null +++ b/regression/strings/StringBuilderChars01/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringBuilderChars01.class +--string-refine --unwind 100 +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/strings/StringBuilderChars02/StringBuilderChars02.class b/regression/strings/StringBuilderChars02/StringBuilderChars02.class new file mode 100644 index 0000000000000000000000000000000000000000..bcfdcce9aa6e031c442128bd7dc67b6a8ef3e37b GIT binary patch literal 797 zcmZvaOH&g;5Xb+sdF*DhArBr2Dhe2M14@wM24yKhPf-uCtO8Dx?0|!tUEPNtCSSm_ zT9s5umEQeKmSxX|kOH|(_w4-p*S+2S`|ppR0Cuo#qJY~v?ig4yq2X>0dE8UpvVj#7 ztGKVDZX%~dYbGAxp$?m2w$8&)1d;T;@IZ#V>k5Z~9WiA0q$i`N3@N+ujv?Lh9l=m+ zOHaIx`&|*dRbqPRbLlZG*vIWN{+Tyj?wvL}Q6Rn3T@_g9M7;Om75|v%sX_*0ujgLC z&5j=jJ@Ha1)Z#d7KbEc|g4TN;gj?I2ifW;RGDG!xh6^b}=|G;G?7Oj8Zp*%mgrg!F z7G_Yiu#OFe@>K;%bUd=~7@G{WDfjuL9WR2w4;bcds!2!F!WN!T-f85U?wROC4DX_hnzM}#sE&gGxb0HT;4Xpl!( zp}i>3%CJ&RHHW+uC^O1*R_L}wmXXb@kHEevA!g~!CLbB?&m88-SJDoJYGl{Wp&eFI zBc$8kkQt!5F+{ea4`B?DKS%Cx1oM|dX$fkE!iW!(pmpe2pql~q2X!4)@@kj0>?BEn hawR{6HGrP}f^_OTGE>;3E(OUzv!1Ey7n5AK{sFA-s>%QW literal 0 HcmV?d00001 diff --git a/regression/strings/StringBuilderChars02/StringBuilderChars02.java b/regression/strings/StringBuilderChars02/StringBuilderChars02.java new file mode 100644 index 00000000000..c5a2bb276f3 --- /dev/null +++ b/regression/strings/StringBuilderChars02/StringBuilderChars02.java @@ -0,0 +1,8 @@ +public class StringBuilderChars02 +{ + public static void main(String[] args) + { + StringBuilder buffer = new StringBuilder("DiffBlue Limited"); + assert buffer.toString().equals("DiffBlue Limitted"); + } +} diff --git a/regression/strings/StringBuilderChars02/test.desc b/regression/strings/StringBuilderChars02/test.desc new file mode 100644 index 00000000000..3a6bde6ef78 --- /dev/null +++ b/regression/strings/StringBuilderChars02/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringBuilderChars02.class +--string-refine --unwind 100 +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringBuilderChars03/StringBuilderChars03.class b/regression/strings/StringBuilderChars03/StringBuilderChars03.class new file mode 100644 index 0000000000000000000000000000000000000000..d124e87d09212ea4e7e130ef347a2a79978fc31b GIT binary patch literal 692 zcmZuv-%ry}6#h=z?QW&O7{7*!A~5VA5fgcn7-48)GUZ{!1bph+3tsFxbKCmI@ZzJ- zYQhpp^xeP77|*T162r?q=k|QxcfNCOfBpIX1Hcy6U5sHt;8q27x%F&utJz#4boKVObwEBPo+UGmJxxD2<2^+sO%}h_FHcVPJ0kZ!emD!@^#+t zNqu0zT<8ZXArsnRmK_Q31OaxU#%MQ;dH*DbcV);eU9>m;Nugm+t literal 0 HcmV?d00001 diff --git a/regression/strings/StringBuilderChars03/StringBuilderChars03.java b/regression/strings/StringBuilderChars03/StringBuilderChars03.java new file mode 100644 index 00000000000..f226901e113 --- /dev/null +++ b/regression/strings/StringBuilderChars03/StringBuilderChars03.java @@ -0,0 +1,8 @@ +public class StringBuilderChars03 +{ + public static void main(String[] args) + { + StringBuilder buffer = new StringBuilder("DiffBlue Limited"); + assert buffer.charAt(0)==buffer.charAt(4); + } +} diff --git a/regression/strings/StringBuilderChars03/test.desc b/regression/strings/StringBuilderChars03/test.desc new file mode 100644 index 00000000000..12f20189434 --- /dev/null +++ b/regression/strings/StringBuilderChars03/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringBuilderChars03.class +--string-refine --unwind 100 +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringBuilderChars04/StringBuilderChars04.class b/regression/strings/StringBuilderChars04/StringBuilderChars04.class new file mode 100644 index 0000000000000000000000000000000000000000..41be0e006830ee6c5258b9a9dd7c23d0ab8554da GIT binary patch literal 1018 zcmZuwTTc@~6#k}rnRZzyw*{&eK~Y-@6r~mg(|Cje4dHW0>jj-eoi4FqsQnw!#$ zgm4SD4ctL2gm%Q`*(gWCK${F0Gcb+`jwD0Rh+VG>*K=ys`ifJxH_M{Pz}6Y`Ij8D) z^9)KX{*pn>)QW;3oO7z;X``|!+!qo|7Zuy7GW5kZay#~0J6X1?rDWc7ooZ=T2Daxt zyYOb!-u3YulSG)~E<( z|8>rx44o^^*4A>lA%=2J#qmT@M%*(og_Mc=NOMe^cz}l-GbUy+XQC5bCLV#>9B5@- zx{&0t>(*R`-pd$qESOlt5>;(QKHJ<81&?ICL=1+&Mux$PU9OW}7S)os?dzQ-bxOkX zdnY%R&2D6}Qp~?f<=@pkQ6YG(K?SX|q)sjQoRs&7u&^t$M8xOz?=ge6D?#*jv5d^B z7f9qKf1iyL#c->kOqu3`UbiUfjw_0Pl%YrU8gxO!v5sMyu`rD!>l~1RlBa;lw<6n1 zyC|)UR&DeM?4tz2BCGp{3?cNPpL_}Z0S!S~?PCPix|JiSxkMA%7i~46NM}rGLRaR; zX4Hs!lGc>8Zt0fx0aFpx(o<=E2yXEvf`m%2itA=Xv>FMZMEuBv{a$Kv@y1{rY5Kl5R=xYg`L*H1$00BG5i6a z)dUio=)1qk81F!VSo<>f&dj;zoVj;?{rUa_Km|_>EZ~NQ6&*JXL~u(kt8tiEli6(@ zcMPoKu7-OC42isNz(PU82E*dI?fcvdM6c@~2;XkH++koR4C=1vir^_j)GEATh*f(I zXGqjUm%j=-P3|=$m@YcD=rUxix3#wY$u7Be_pDS8JkdSdk%ja1z;3;NX@3~u$tHuo z+j1|+je0NiTKu_?RQYk)ekfdrd)0Tg=WlIqN>&poq#3f86)vC*$pdkEy6=X3wI(_u z;Et>)ns|VRCK5=R*hGmTbu@yxjVVsUmWfAr%#fRr?@fAg=y^SlVd*Mk8p6wnrGndQp`f(u3ZZpM8ZeoE%Zh&cm=a)rLEN;Wj)p`%PXSvu9hexs}*M_GPqu`==kq|)X9^L=Qs&xl38 VL7kCK>`D>^5%ZaR)U}c3^}k&QvyK1& literal 0 HcmV?d00001 diff --git a/regression/strings/StringBuilderChars05/StringBuilderChars05.java b/regression/strings/StringBuilderChars05/StringBuilderChars05.java new file mode 100644 index 00000000000..120871f8a9d --- /dev/null +++ b/regression/strings/StringBuilderChars05/StringBuilderChars05.java @@ -0,0 +1,10 @@ +public class StringBuilderChars05 +{ + public static void main(String[] args) + { + StringBuilder buffer = new StringBuilder("DiffBlue Limited"); + buffer.setCharAt(0, 'H'); + buffer.setCharAt(6, 'T'); + assert buffer.toString().equals("HiffBllTe Limited"); + } +} diff --git a/regression/strings/StringBuilderChars05/test.desc b/regression/strings/StringBuilderChars05/test.desc new file mode 100644 index 00000000000..2bcbdbab934 --- /dev/null +++ b/regression/strings/StringBuilderChars05/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringBuilderChars05.class +--string-refine --unwind 100 +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringBuilderChars06/StringBuilderChars06.class b/regression/strings/StringBuilderChars06/StringBuilderChars06.class new file mode 100644 index 0000000000000000000000000000000000000000..e3597f40f878e29533d15df6a564a8735982154e GIT binary patch literal 856 zcmZuvU2hUW6g|Vo?y}t$*nU8*RjO5iYN=ZLLSqzK;{)mgji%L?g&peD1$1_|KZZZx zvzkC+6MgqL8RH$G#Z+Eq?(Up>&bc4I{(S!dU>iFo=5STVs)1`JBDk)OTmlx>RCL3@ zO%v<5rQ@~8;V;8>gUbU2riZp8It)wsx3v@J)G2vR=eSf4r05)%RpM+taGD=pI3I_2vdLiV zHoY;qS?`9j$)5>DwLD6zgu-*VtiE@ozqPZeSS_SsGh{9+jG+vvJ<)1aypZQ=qAddM zs*DW_cX7``5-AItC^4j69?*L&#}B+pt0ly99a|Re;{ii%vM z)c!{#KFNI5IN{BJVKG0w8@lADT>4b(O1|(PWL!>}S`>6gnj}62NQi$#&ygDc6gr-N zNquCgT%egICq}Ct4W7p4a$iX9UQ|re3PO6IsUKmDmS~QajHR-wi4;XaO@vM7JbkUw z&FGF72Vh?m5DRo_!=DTZEMkdb1${@U5xR?Kh#cC{0b;d{KH_h_LhB(zp>7*}Bzl-R zgLyc>%umG^8S>ePQ5>h`)yRg90t{s6j{){u?Qxc(Hq)$ literal 0 HcmV?d00001 diff --git a/regression/strings/StringBuilderChars06/StringBuilderChars06.java b/regression/strings/StringBuilderChars06/StringBuilderChars06.java new file mode 100644 index 00000000000..f3b3b6bc8d8 --- /dev/null +++ b/regression/strings/StringBuilderChars06/StringBuilderChars06.java @@ -0,0 +1,9 @@ +public class StringBuilderChars06 +{ + public static void main(String[] args) + { + StringBuilder buffer = new StringBuilder("DiffBlue Limited"); + buffer.reverse(); + assert buffer.toString().equals("detimiL eTlBffiiH"); + } +} diff --git a/regression/strings/StringBuilderChars06/test.desc b/regression/strings/StringBuilderChars06/test.desc new file mode 100644 index 00000000000..4a711edf496 --- /dev/null +++ b/regression/strings/StringBuilderChars06/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringBuilderChars06.class +--string-refine --unwind 100 +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring From c7bcdf4635b25dc8b77415781fd8463200469c0a Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Wed, 22 Feb 2017 14:18:42 +0000 Subject: [PATCH 007/699] =?UTF-8?q?=C2=A0added=20test=20cases=20related=20?= =?UTF-8?q?to=20stringBuilder=20constructors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucas Cordeiro --- .../StringBuilderConstructors01.class | Bin 0 -> 797 bytes .../StringBuilderConstructors01.java | 13 +++++++++++++ .../strings/StringBuilderConstructors01/test.desc | 8 ++++++++ .../StringBuilderConstructors02.class | Bin 0 -> 711 bytes .../StringBuilderConstructors02.java | 8 ++++++++ .../strings/StringBuilderConstructors02/test.desc | 8 ++++++++ 6 files changed, 37 insertions(+) create mode 100644 regression/strings/StringBuilderConstructors01/StringBuilderConstructors01.class create mode 100644 regression/strings/StringBuilderConstructors01/StringBuilderConstructors01.java create mode 100644 regression/strings/StringBuilderConstructors01/test.desc create mode 100644 regression/strings/StringBuilderConstructors02/StringBuilderConstructors02.class create mode 100644 regression/strings/StringBuilderConstructors02/StringBuilderConstructors02.java create mode 100644 regression/strings/StringBuilderConstructors02/test.desc diff --git a/regression/strings/StringBuilderConstructors01/StringBuilderConstructors01.class b/regression/strings/StringBuilderConstructors01/StringBuilderConstructors01.class new file mode 100644 index 0000000000000000000000000000000000000000..c7052b38c1f2d4b0cf579a5014877469af80212a GIT binary patch literal 797 zcmaJ;-%ry}6#nkoty|a0Rt8K52#7j`ax##qp@0|O6-~Ds(^A~_ktedEyX<*t!4o!8;6fvvf-4e=} zQ`x+M1rsF&yJun%_YFK?7+-Xvh|5@nLG(gIPT%Jq13O?SY>7a`PZ+e;(i;Z76MCFs ztSbV(mz?yue67ILIB`V4Fxfin9y=eM4c`d{8@*VHVDMNCR(i4HzTb5|qLKQWJsedoJoKWqDwB8d(M}0rx z>c3^-7RD?rVVR+k4L-Y){Zh(MGBp2lw}BN4t5{>GW(!{RkGUI@{??9?InlaVe!=I# zAbywHxI_MB3pzeoPsVvX5|Vq@gvhTrp$7SWfO&ep3cWF_Hk1y^G!PBc=(Oo?h9aYw zUmk*eQ$UQE)^`_z)6+dT4#UPh5n1w-k9!26}Q$9^x+Ay(Af(~I}lDbuB7ib%p8h!OT pp&QrIHd75i%`Tt8I)$Nsg|7X8kzH~nQ!UFQXFXMB+)g>%`3wBgq3Qqt literal 0 HcmV?d00001 diff --git a/regression/strings/StringBuilderConstructors01/StringBuilderConstructors01.java b/regression/strings/StringBuilderConstructors01/StringBuilderConstructors01.java new file mode 100644 index 00000000000..efb5524c2b8 --- /dev/null +++ b/regression/strings/StringBuilderConstructors01/StringBuilderConstructors01.java @@ -0,0 +1,13 @@ +public class StringBuilderConstructors01 +{ + public static void main(String[] args) + { + StringBuilder buffer1 = new StringBuilder(); + StringBuilder buffer2 = new StringBuilder(10); + StringBuilder buffer3 = new StringBuilder("diffblue"); + + assert buffer1.length()==0; + assert buffer2.length()==0; + assert buffer3.length()>0; + } +} diff --git a/regression/strings/StringBuilderConstructors01/test.desc b/regression/strings/StringBuilderConstructors01/test.desc new file mode 100644 index 00000000000..2c60f9bbbda --- /dev/null +++ b/regression/strings/StringBuilderConstructors01/test.desc @@ -0,0 +1,8 @@ +KNOWNBUG +StringBuilderConstructors01.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/strings/StringBuilderConstructors02/StringBuilderConstructors02.class b/regression/strings/StringBuilderConstructors02/StringBuilderConstructors02.class new file mode 100644 index 0000000000000000000000000000000000000000..2bfe2e70d3b3e6c08aaebe6686cc1326c7249f56 GIT binary patch literal 711 zcmaJfvG^o5LlGTq_EN2)qisVR@1?^3_*$Iic&?04-togLakm#|+Ly1C zky^T>?Pe+rr0#G@sm}Z~*2&{1kBqp72~-Jlw-a44SUFIKhy5^<2D$3N!?=evtP>g| z&hzVzUuqp|!oq*jI(Xorg*Kr!5_sD`mVQc@Y5lw9l03^qnA`$fvbNhi+v-TG6Y>Ih ze1S}qmcdPJJhe3A08f9Pw^iW{0#s|5me{jFW)^(b__oNF*cLa2pf3i9Nj^*YBQd#- zDfSKY9aAl~%NMZr>h=(Y?pG8Cn0{Ed&rup+>;lf-5apjn$I5jkn8V_5S+U7qXqs Date: Wed, 22 Feb 2017 14:19:25 +0000 Subject: [PATCH 008/699] =?UTF-8?q?=C2=A0added=20stringBuilder=20methods?= =?UTF-8?q?=20insert,=20delete=20and=20deleteCharAt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucas Cordeiro --- .../StringBuilderInsertDelete01.class | Bin 0 -> 1924 bytes .../StringBuilderInsertDelete01.java | 46 ++++++++++++++++++ .../StringBuilderInsertDelete01/test.desc | 8 +++ .../StringBuilderInsertDelete02.class | Bin 0 -> 1725 bytes .../StringBuilderInsertDelete02.java | 40 +++++++++++++++ .../StringBuilderInsertDelete02/test.desc | 8 +++ .../StringBuilderInsertDelete03.class | Bin 0 -> 1819 bytes .../StringBuilderInsertDelete03.java | 43 ++++++++++++++++ .../StringBuilderInsertDelete03/test.desc | 8 +++ 9 files changed, 153 insertions(+) create mode 100644 regression/strings/StringBuilderInsertDelete01/StringBuilderInsertDelete01.class create mode 100644 regression/strings/StringBuilderInsertDelete01/StringBuilderInsertDelete01.java create mode 100644 regression/strings/StringBuilderInsertDelete01/test.desc create mode 100644 regression/strings/StringBuilderInsertDelete02/StringBuilderInsertDelete02.class create mode 100644 regression/strings/StringBuilderInsertDelete02/StringBuilderInsertDelete02.java create mode 100644 regression/strings/StringBuilderInsertDelete02/test.desc create mode 100644 regression/strings/StringBuilderInsertDelete03/StringBuilderInsertDelete03.class create mode 100644 regression/strings/StringBuilderInsertDelete03/StringBuilderInsertDelete03.java create mode 100644 regression/strings/StringBuilderInsertDelete03/test.desc diff --git a/regression/strings/StringBuilderInsertDelete01/StringBuilderInsertDelete01.class b/regression/strings/StringBuilderInsertDelete01/StringBuilderInsertDelete01.class new file mode 100644 index 0000000000000000000000000000000000000000..7858a392c3fa16230e3ae30f6ebaf25aecdb7726 GIT binary patch literal 1924 zcmb7FOK%%h6#lLsbM48vnK*GAH!o94ahikQo|^=j3y zY_n3XE}2z5S279=Y>Po!Fw3TWp1~a(xys;4RSE_}=c-vY)@wI&hP5fkq`0Y@Wrp6^ z_Ua9NS069w<(=^j+cL{L^I~IQ!`Acft?BRA`5c$&T#hRouhC^0d<*$f^B{SnQnT{L zvMJ0)8zwH)%u>Oy(q-Y~l2I~jV`4Hc4pMLuFVOyiSuEyCHQ|YERBeXv({40vD0m$k zbT>^1n*uTdt_rv&;JSdUfGq*r0^U&YCf-tT0?#wdClc{QBB4#i&uEhqjgK~~t!TDY zGc>bkYP*I-LtYp0)Py@)%RRcXg17MwL*KrCi>=sSw5*DyKu1nN9$AKi*6o&pb zapNc`Fi>Pr_kFmWyJ6%hY~BBnzeB`^VFuTBimJn`XM`ahOCQL4!`S@Dfu%$K%s;)M zp>4ZiD3;z%wX+x%gmk(cWiXcBIzr#}2-<&?{YyvKUp_*=)K2fSE3NSN#GWNmSS90w znqI0hgklGR-^vH|vr?#cPwHLWTBLLj#M)j+YOtx{_bVk;qPK!NysEI&S&wRDvR>87WF^(iWVu?*WPL(XB{fgTRh`hM+Jyf4x~x`6 z?oi8_bY&3NR2&4{V*(nY=HOUM zlq3h8%}L1PKyArh2VE_hIKige%N=w#<*?sDPgCxb9fYn$=&0Vgz;_7mAruJ&`y52} z(D4w*$))}uBZ^A20it*o}D3N|G{qA$l9e7HhU-h_{|6=gPfGh=l<>cCiZR5PA0sS?Q5L}%n}mkbf0+V;+~A xW1ObIIC(npq->_^^#ODRhaE)sz&&5XpA5B`2V@uzBGw;ot_ueT4TX( zm|In=%)mAn={7$DquYs-1(>wR+PjS&Oy^JJt?y zu4z}xmXoiEBp0lzxNaLq6hz{ z`_DMG12gzGbEK`^>L)`gnct&YJJ{U#o~382447kb$hx87}kB>7)QYO8F0&@`(JhG=q6^SgS`o$23|JXfVB zOAoGWHEhQ!KfOZq&fF#$=)G>x+Zdtm3&8ZaxVyysVB*CPzD%=G8X1j&qxZqSCBkr+ zP;MMmc#xPUHc(W^y}M&qNH1eVnBBaMOn8CMXpy0MMW@O z)=Pw3HwhKpB@DLKRlQEUPp=hLrD;iDnhxlET8==P;bHkyFamyBeTZQ3KGaz)q4|$_ z=<|m)4e@O~Tty$QL4%19 zD(FWY1NabOe1t)KiU>YK6rW=Vw-CdZh~q0HaF;&J-(VQ`NVW$g&d(&?FC^Trbk1)i z+wUaYAEd^gq|0A8!WdqqKgh!Vp^3(kJ?FrkK* literal 0 HcmV?d00001 diff --git a/regression/strings/StringBuilderInsertDelete02/StringBuilderInsertDelete02.java b/regression/strings/StringBuilderInsertDelete02/StringBuilderInsertDelete02.java new file mode 100644 index 00000000000..d0e4923ad3c --- /dev/null +++ b/regression/strings/StringBuilderInsertDelete02/StringBuilderInsertDelete02.java @@ -0,0 +1,40 @@ +public class StringBuilderInsertDelete02 +{ + public static void main(String[] args) + { + Object objectRef = "diffblue"; + String string = "test"; + char[] charArray = {'v', 'e', 'r', 'i', 'f', 'i', 'c', 'a', 't', 'i', 'o', 'n'}; + boolean booleanValue = true; + char characterValue = 'K'; + int integerValue = 7; + long longValue = 10000000; + float floatValue = 2.5f; + double doubleValue = 33.333; + + StringBuilder buffer = new StringBuilder(); + + buffer.insert(0, objectRef) + .insert(0, "-") + .insert(0, string) + .insert(0, "-") + .insert(0, charArray) + .insert(0, "-") + .insert(0, charArray, 3, 3) + .insert(0, "-") + .insert(0, booleanValue) + .insert(0, "-") + .insert(0, characterValue) + .insert(0, "-") + .insert(0, integerValue) + .insert(0, "-") + .insert(0, longValue) + .insert(0, "-") + .insert(0, floatValue) + .insert(0, "-") + .insert(0, doubleValue); + + String tmp=buffer.toString(); + assert tmp.equals("33.333-2.5-10000000-7-K-true-ifi-verification-test--diffblue"); + } +} diff --git a/regression/strings/StringBuilderInsertDelete02/test.desc b/regression/strings/StringBuilderInsertDelete02/test.desc new file mode 100644 index 00000000000..f78bf3f983a --- /dev/null +++ b/regression/strings/StringBuilderInsertDelete02/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringBuilderInsertDelete02.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringBuilderInsertDelete03/StringBuilderInsertDelete03.class b/regression/strings/StringBuilderInsertDelete03/StringBuilderInsertDelete03.class new file mode 100644 index 0000000000000000000000000000000000000000..6e238d7caea3b3ed8af71e3eb7a942336512b1ad GIT binary patch literal 1819 zcmah}O>7%Q6#mBE-LW^DX5*j4Zho3V0VnMyX_7i^5{gr&0XIJd61R22-`ZZ6Ev^mg zbtEo`0~fe(tEvbIi3_NQNX)! zGe7=)?*V`rSSm&^6~J@=GctVvZr*rbN{s+YDs}7A2RlF9;W(uth$#Wd0A|H_TEH0r za{}fCEC_g3z*zy$2}lW86mU*JI*4H`1#n))GM?vnLB$}ZI5H|OV1;9qA$-iN)hx%g ztCiZ4T{H7#tH{8%7?cIOV!LM<{E5*^3{tvUv>19;?TWQtzn-_8P2o(2>!w{{=u2#` zUNd*hiLzO_I|TOToI5Hu%%%euV{Ex7+%Bc8jj)#hUE0LF*Sbb(nj7Hf>|aa_o{_Fhx-fk(1HRk3kQ;p7~74F!-y`d)yG z`D<2z4j%p=1s-v124?VWr%7MCQB#KTL}s6I&0zDR`#wFA&-~*Hn%0gBh7+0Xbf<_T z!XcCCU|Do7&s0wpEKH z{u`gvP^@?AX1T@?P3+UGEhAmzp1n>V4qzou*7 z$T`2hlg&xGmCebzlg%l*oy~E*l+6VM(-ply$aRx2pu2>@#&=b(67SM0*>x!?=_^TD z=Sd|3X_kkS)4>S%8TCGbxw}y3w7BL!?xD*c(mZtgPY7sI!^5FARTK|Btw~h!ptrf~ zp|{P+C)DD7+(Wp<`-2`LEgn-nL@&oRoyI;IWt|rF6Y&t6>;4MyT}0#Ep~D^qcF}bo zgOuaYx1w;qM&Ukc)L5n}EA*!a5&?R6g4l$LE9j!9M}vuOl+c4Jdhsqocn@KGfCxTB z6d$7xH_(qy5W{DP;|mL}PhG|@Q5IF56i;4m0tlF!dEPE&FTVB%pr%rtZddPBn=j_iU Date: Wed, 22 Feb 2017 14:20:06 +0000 Subject: [PATCH 009/699] =?UTF-8?q?=C2=A0added=20string=20methods=20equals?= =?UTF-8?q?,=20equalsIgnoreCase,=20compareTo=20and=20regionMatches?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucas Cordeiro --- .../StringCompare01/StringCompare01.class | Bin 0 -> 1325 bytes .../StringCompare01/StringCompare01.java | 47 ++++++++++++++++++ regression/strings/StringCompare01/test.desc | 8 +++ .../StringCompare02/StringCompare02.class | Bin 0 -> 721 bytes .../StringCompare02/StringCompare02.java | 14 ++++++ regression/strings/StringCompare02/test.desc | 8 +++ .../StringCompare03/StringCompare03.class | Bin 0 -> 723 bytes .../StringCompare03/StringCompare03.java | 14 ++++++ regression/strings/StringCompare03/test.desc | 8 +++ .../StringCompare04/StringCompare04.class | Bin 0 -> 703 bytes .../StringCompare04/StringCompare04.java | 9 ++++ regression/strings/StringCompare04/test.desc | 8 +++ .../StringCompare05/StringCompare05.class | Bin 0 -> 642 bytes .../StringCompare05/StringCompare05.java | 11 ++++ regression/strings/StringCompare05/test.desc | 8 +++ 15 files changed, 135 insertions(+) create mode 100644 regression/strings/StringCompare01/StringCompare01.class create mode 100644 regression/strings/StringCompare01/StringCompare01.java create mode 100644 regression/strings/StringCompare01/test.desc create mode 100644 regression/strings/StringCompare02/StringCompare02.class create mode 100644 regression/strings/StringCompare02/StringCompare02.java create mode 100644 regression/strings/StringCompare02/test.desc create mode 100644 regression/strings/StringCompare03/StringCompare03.class create mode 100644 regression/strings/StringCompare03/StringCompare03.java create mode 100644 regression/strings/StringCompare03/test.desc create mode 100644 regression/strings/StringCompare04/StringCompare04.class create mode 100644 regression/strings/StringCompare04/StringCompare04.java create mode 100644 regression/strings/StringCompare04/test.desc create mode 100644 regression/strings/StringCompare05/StringCompare05.class create mode 100644 regression/strings/StringCompare05/StringCompare05.java create mode 100644 regression/strings/StringCompare05/test.desc diff --git a/regression/strings/StringCompare01/StringCompare01.class b/regression/strings/StringCompare01/StringCompare01.class new file mode 100644 index 0000000000000000000000000000000000000000..38f0d216e1cf640abd23b0356795e344fe3faa94 GIT binary patch literal 1325 zcmZ`(T~8BH5IwiucDH4hmMtx3(h@YTe`KcLU*+!l(~l5A%8&YU?j_snEJ|N3|YU+%&2v1U&abZ%zOvsq@V+zwUE;ED%jY@^vj%k%Ecg>2C zE%H1A+hp+0n`P6v&EQUqK4Os4R-Q8imd!F>t(LOfUKd~rlnk@X5J@~<-ZEYqlSQLk zm|Sygvs{=HiQ1ZD+jYE*E7UoIGM_6R^ZVDVs-5HaOu^RO$V^+MZNuhM(-VSI zMHmr=U@JcrcX-7S;TZYa)p)RvoKkIA$)sPVxACUgkC(E$TC7G-Dz+UTDTt zT*WmNA#^iDPfIPH=(A+omaXDCZm774Srv1b7v>hJ($ckz+bZs0;h&x#WVd+EA<5ea z#Sl)km(R;zRE=V#1<>G{8>Kk~8-PrqY}q_*ROtR~xd`gZHDq14&cI}7TsAL|P%DO$ zd&a43G?Dqgu}nr(jwLqFj0H{wOc!azXhHJ4V%j|4)RXqYsZxOUYZC*swK}ag3r58R z=*tai5)raJbn2rwqqk@50PLLrB1+axHfe60ih2np9eDTA^&Y-mbR5FJae$6b6xnOzPQ|1e)OHE=^l);#1}&()Jtb=R$CJYU zqtzcu3ja{VSqg58EU%|9gn$|VSQgDy8c>3LeVuQ?HZqA+F-*eMsfkxu@PVn z0Yi1>aQC|GmrBKo3j0Uf#k~NVXfPCKNpJcmBGi99U8PZ(N({+Nm+SDYNJy&D{=XmX zc9S|=m=U%{)P8E-KqOL$!PFG>Oiu`)-XCFwe$S_mWyPu~gH9Gm5c9Ma=(bEdqusuL z3HHGRqDZTgJ~HG`LYdAcl*6WEV6B|#l&$Uq>!Ia+M)p0N3zR;>KF8cwIER;TzZ;@V zO0+~>D04MXRnLOxc>!vY}zGCxsq)0ro)H>S?EQwu<;Oe(o^xY-M2txvFL#fE+dAG=9}&bf6w*}J6+EijpW_nzQZ$(0$nuE^& z1L<^HG}^+Fu|1*r)AU9nkxGmfu4rg_MgR?efNgp{pI(*~tELaySs+EM(psR?7DYxe zd;1*hgGoe@Rwun=$f1NX?M>>CZY_$9a;96hdUtH=uH}7(J%@9K(nn8;+j@W!u$jC04SR*7r<|isH*6Gia*~-G&LFxf0l}RNxhijj~wmu=d TB)_z2h_c88k4-ZhsrHrMId_!7 literal 0 HcmV?d00001 diff --git a/regression/strings/StringCompare03/StringCompare03.java b/regression/strings/StringCompare03/StringCompare03.java new file mode 100644 index 00000000000..fbd881efd48 --- /dev/null +++ b/regression/strings/StringCompare03/StringCompare03.java @@ -0,0 +1,14 @@ +public class StringCompare03 +{ + public static void main(String[] args) + { + String s3 = "Automatic Test Generation"; + String s4 = "automatic test generation"; + + // test regionMatches (ignore case) + if (!s3.regionMatches(true, 0, s4, 0, 5)) //false + assert true; + else + assert false; + } +} diff --git a/regression/strings/StringCompare03/test.desc b/regression/strings/StringCompare03/test.desc new file mode 100644 index 00000000000..fa518907143 --- /dev/null +++ b/regression/strings/StringCompare03/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringCompare03.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringCompare04/StringCompare04.class b/regression/strings/StringCompare04/StringCompare04.class new file mode 100644 index 0000000000000000000000000000000000000000..cb288719581cd9f599cc0f3c56b08cebad443698 GIT binary patch literal 703 zcmZ`%O>fgc5PcInw&OU|b(<1C3TqKtf94kP4~oX=AUVEs0&(4ibN* z7ml1MQX^3b?))bZvo38!1=4DFc0S&FGrK>2effxynRuAR_`D5Ud>)tNaPUXs*2_nC&EzgsF~- zd$F=4KG*f|pK#r8nN{q1g^s<{7H7uLGD2;c3B<07BM5uBZH@CV%O zCZjZzFO`Oxy(nuZ!()-kN3AUl=wS*z!M_g9%(={R9bP5a{UnKcAEbvGZg_ZzCZRDY zd3M?4i!@DAZsQu0jWrMJ*!YX*P47sCIicSCcW0IGLg-%dpPW}rG||u=@ThrEk<3&o zqbo@~pM1mtp7Q|~`MErPO!6DL6SfR63VhzD`8Lld@mXFUgFfp-1iV{?lTg77X4%%M zhg@p#xq6P$eqfAYc7pQmDXbIJH#g2;`?Zg#p2OK6qw-y2l?to?Cfj8eVzC7NCH!gX y?5To&V#UTBFLvF$($p%*f$6|KL-ho<`3a`+1=a-fQlG{tqvSo+T{H^HTfYIp^o!pB literal 0 HcmV?d00001 diff --git a/regression/strings/StringCompare04/StringCompare04.java b/regression/strings/StringCompare04/StringCompare04.java new file mode 100644 index 00000000000..c602594930f --- /dev/null +++ b/regression/strings/StringCompare04/StringCompare04.java @@ -0,0 +1,9 @@ +public class StringCompare04 +{ + public static void main(String[] args) + { + String s1 = new String("test"); + String s2 = "goodbye"; + assert s2.compareTo(s1)==13; //false + } +} diff --git a/regression/strings/StringCompare04/test.desc b/regression/strings/StringCompare04/test.desc new file mode 100644 index 00000000000..f1b2a9790cc --- /dev/null +++ b/regression/strings/StringCompare04/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringCompare04.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringCompare05/StringCompare05.class b/regression/strings/StringCompare05/StringCompare05.class new file mode 100644 index 0000000000000000000000000000000000000000..70bbad48ef69bb1c1417507aa918529a4e104d94 GIT binary patch literal 642 zcmZvZ-%k@k5XZlJ*Sl-4*Waa7u}Be3!32DOCkWA0eJc7;V^Vn9wwq>adq?)J{xSUn z;2BJ8A_>0xHxa_@X=x<9?99&0e&#!~e{O$W1K7nY7cQy}o+R{zJ7%yCq%WgG2D7pGl_Aj#`hp?XlD_yf8Fz*H zqKhdp=F(@VG)`JW{+;iPxIfrwM@ssGef==gj(G3e5kHOVNfbl!pf~ylciX{4^~6W1 zQRTnSn!)&#EAeJ;TLV30kY&g}gj458gpp3Kdq~4$s4i;W&8PaHRG>)r1GIw|9yaju zKk(=7Q1l{(rN-l<g&<33 zj&3!wjI6aa1G~_L$kS=ZL536xD3Y&BJM`2byM6_uQ#5Btv|bm@GuY=ST*8_neFeKS zgY#Q+jF?k_MZQH6Y`Qxr5wT9U5=B!mZcuVi&XC5Xdqul(YoJg}{zPgDCvlF1`2*I1 SI#;JD77XvLo}m&qUA_a4#C#3_ literal 0 HcmV?d00001 diff --git a/regression/strings/StringCompare05/StringCompare05.java b/regression/strings/StringCompare05/StringCompare05.java new file mode 100644 index 00000000000..8764cb5c99a --- /dev/null +++ b/regression/strings/StringCompare05/StringCompare05.java @@ -0,0 +1,11 @@ +public class StringCompare05 +{ + public static void main(String[] args) + { + String s1 = new String("test"); + if (s1 == "test") // false; they are not the same object + assert true; + else + assert false; + } +} diff --git a/regression/strings/StringCompare05/test.desc b/regression/strings/StringCompare05/test.desc new file mode 100644 index 00000000000..159809fac0f --- /dev/null +++ b/regression/strings/StringCompare05/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringCompare05.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring From 48a1df89abbf0de1d3cdda59fe82c3f06be5e139 Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Wed, 22 Feb 2017 14:21:49 +0000 Subject: [PATCH 010/699] =?UTF-8?q?=C2=A0added=20test=20cases=20related=20?= =?UTF-8?q?to=20string=20method=20concat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucas Cordeiro --- .../StringConcatenation01.class | Bin 0 -> 864 bytes .../StringConcatenation01.java | 17 +++++++++++++++++ .../strings/StringConcatenation01/test.desc | 8 ++++++++ .../StringConcatenation02.class | Bin 0 -> 719 bytes .../StringConcatenation02.java | 10 ++++++++++ .../strings/StringConcatenation02/test.desc | 8 ++++++++ .../StringConcatenation03.class | Bin 0 -> 1099 bytes .../StringConcatenation03.java | 17 +++++++++++++++++ .../strings/StringConcatenation03/test.desc | 8 ++++++++ .../StringConcatenation04.class | Bin 0 -> 899 bytes .../StringConcatenation04.java | 10 ++++++++++ .../strings/StringConcatenation04/test.desc | 8 ++++++++ 12 files changed, 86 insertions(+) create mode 100644 regression/strings/StringConcatenation01/StringConcatenation01.class create mode 100644 regression/strings/StringConcatenation01/StringConcatenation01.java create mode 100644 regression/strings/StringConcatenation01/test.desc create mode 100644 regression/strings/StringConcatenation02/StringConcatenation02.class create mode 100644 regression/strings/StringConcatenation02/StringConcatenation02.java create mode 100644 regression/strings/StringConcatenation02/test.desc create mode 100644 regression/strings/StringConcatenation03/StringConcatenation03.class create mode 100644 regression/strings/StringConcatenation03/StringConcatenation03.java create mode 100644 regression/strings/StringConcatenation03/test.desc create mode 100644 regression/strings/StringConcatenation04/StringConcatenation04.class create mode 100644 regression/strings/StringConcatenation04/StringConcatenation04.java create mode 100644 regression/strings/StringConcatenation04/test.desc diff --git a/regression/strings/StringConcatenation01/StringConcatenation01.class b/regression/strings/StringConcatenation01/StringConcatenation01.class new file mode 100644 index 0000000000000000000000000000000000000000..8a2ee685b444d098b7dac80fa33ad12df6776cf4 GIT binary patch literal 864 zcmZuvTW=CU7(D|EyDVD^ON)rb(pnJ;Et>SnHb$iyA83uin6y3(%d}a#U2u0X@vra) zd{z^hsL^+SlN!HS%EiX)W-j05%sFS~=bta%0qmfz!$4lcO${pv=qTv8g;ffgc5PcilS=(_*>b4;*1X3uFw1^^9POT7-f;gmb2tuNqHqN%%;@ZIyji!q$xXRIT z!LiJ->f#!%bF48etcf(0Nv7f`-Bqa=gmTEh_8H1MDpJ`42BY11#b9>hp=7A`R3xA0 z#{-$X)WvjgEL6l$Z@=jsiT7eN6w%>kKTA|}xUGS6{Y(UJ_r$2E=eWUO?*!pra$Cb>k=ynT&*1b@$#KP3z$Ts)T$dMxzfckuf-}U3GBqILxI74|9~5p0%in zhnu*?(3nYjG@bKFlEewa(tn$Av^{jN&QO~{Ukr|9KrPRuCSY<&zRN|J5?%Y;_!Gc( zhit6QXu2VJO->DEsuDRo6GR4OIUSJE`&gwbtI$QVT0@UTkpZTMr?p03P1+gl*7_;f zCtZknTFXU}On{FCigjs>5`lsHeyQghd!J#BvAE$|Cn%3m`3C;_6!wov`nGTUo7U8& zg1QciVvDHC^l(yO({JWrk+L32ztH4ZqPI@@`kBtHLJ%1hm^p28R9eNpjAj*eTnt>BK1 z72MU)4}-x7({yuC5*_!j$}rMncoa77iR(Hp!c>=Rz_2B}MQGBZqN&l$$QM>PMSp0h;6)0DI| zhT=Iqr{~=1;%e@Hdc=nouX`l;G*1{rCQJ9)xn3tHl8>swvs_XA+g-Ac-=Yh$;VyYR zO_m2(W<*Ykc2Q6f7^LqI{f*PgXpK)FgMF4j4AVCe9Fk{n5hJvh(63MsqqSm0HjU`k z5n@I>_5+EX=*(;zN~sO?ZLr%uLh=xUbB5MN>JX{#(07i}_iKhOV#bATOn?uOk+VoC zBoYY8BSrf-sZP+Nl5#0Y#bszzTZ$~$M?SlN=Tv7I8C)WC8j%yMC>ZU$xd0v(yc|>p i^c(3mGKWxNpAd_FL9&-KEM9WO5z!yY7L5gx#{U2gd-sO` literal 0 HcmV?d00001 diff --git a/regression/strings/StringConcatenation03/StringConcatenation03.java b/regression/strings/StringConcatenation03/StringConcatenation03.java new file mode 100644 index 00000000000..56d397b96dc --- /dev/null +++ b/regression/strings/StringConcatenation03/StringConcatenation03.java @@ -0,0 +1,17 @@ +public class StringConcatenation03 +{ + public static void main(String[] args) + { + String s1 = "Happy at"; + String s2 = " DiffBlue"; + + System.out.printf( + "Result of s1.concat(s2) = %s\n", s1.concat(s2)); + String tmp=s1.concat(s2); + assert tmp.equals("Happy at DiffBllue"); + + tmp=s1; + System.out.printf("s1 after concatenation = %s\n", s1); + assert tmp.equals("Happy at"); + } +} diff --git a/regression/strings/StringConcatenation03/test.desc b/regression/strings/StringConcatenation03/test.desc new file mode 100644 index 00000000000..26ccc899a87 --- /dev/null +++ b/regression/strings/StringConcatenation03/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringConcatenation03.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringConcatenation04/StringConcatenation04.class b/regression/strings/StringConcatenation04/StringConcatenation04.class new file mode 100644 index 0000000000000000000000000000000000000000..047d2b908ab423d6ea731ab22809263555c418d8 GIT binary patch literal 899 zcmZ`%U2hUm5IvU#c3HOa(H5~Ex@xOXT4)vZ0W=z_@qwxdM$`Iqfm^Z_c5!zx>0jXw z_-svRqEX-dPa5YgQfSmsyZP?OGmhc14?k9WX?zmTmbD7?fQ86+^h@ zv;{+=ZrS45pw|@cOBqZLJ#N_yncSQD5r5B1U2b*_NKT7--aHa5LY53{W5>V+Bp702#(=V5;1+H(WT%)%6LlWDuH!N+ z{I{718VhDQr5B`@Pw|5HDm0TI{dqUdqc4LF8LGLz zg`U-Z+-4>JANHttH{e~5($DftKs5NowEJ3@wu5Hd7M|sb_L&$oQhz`Xv>FGrWCraX zz>--hDcuxM*GSQsroUCPjBI4%6zro6#5|qRz)1tZ0v72mLp$VE$QIL~dSUMbN;(|= zipaiFXp9hjeFAleh0U}!LTrfm7wG$^h<}%yp@1_J6cQnhDBV Date: Wed, 22 Feb 2017 14:22:27 +0000 Subject: [PATCH 011/699] =?UTF-8?q?=C2=A0added=20test=20cases=20related=20?= =?UTF-8?q?to=20string=20class=20constructors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucas Cordeiro --- .../StringConstructors01.class | Bin 0 -> 1008 bytes .../StringConstructors01.java | 19 ++++++++++++++++++ .../strings/StringConstructors01/test.desc | 8 ++++++++ .../StringConstructors02.class | Bin 0 -> 652 bytes .../StringConstructors02.java | 9 +++++++++ .../strings/StringConstructors02/test.desc | 8 ++++++++ .../StringConstructors03.class | Bin 0 -> 713 bytes .../StringConstructors03.java | 10 +++++++++ .../strings/StringConstructors03/test.desc | 8 ++++++++ .../StringConstructors04.class | Bin 0 -> 736 bytes .../StringConstructors04.java | 10 +++++++++ .../strings/StringConstructors04/test.desc | 8 ++++++++ .../StringConstructors05.class | Bin 0 -> 736 bytes .../StringConstructors05.java | 10 +++++++++ .../strings/StringConstructors05/test.desc | 8 ++++++++ 15 files changed, 98 insertions(+) create mode 100644 regression/strings/StringConstructors01/StringConstructors01.class create mode 100644 regression/strings/StringConstructors01/StringConstructors01.java create mode 100644 regression/strings/StringConstructors01/test.desc create mode 100644 regression/strings/StringConstructors02/StringConstructors02.class create mode 100644 regression/strings/StringConstructors02/StringConstructors02.java create mode 100644 regression/strings/StringConstructors02/test.desc create mode 100644 regression/strings/StringConstructors03/StringConstructors03.class create mode 100644 regression/strings/StringConstructors03/StringConstructors03.java create mode 100644 regression/strings/StringConstructors03/test.desc create mode 100644 regression/strings/StringConstructors04/StringConstructors04.class create mode 100644 regression/strings/StringConstructors04/StringConstructors04.java create mode 100644 regression/strings/StringConstructors04/test.desc create mode 100644 regression/strings/StringConstructors05/StringConstructors05.class create mode 100644 regression/strings/StringConstructors05/StringConstructors05.java create mode 100644 regression/strings/StringConstructors05/test.desc diff --git a/regression/strings/StringConstructors01/StringConstructors01.class b/regression/strings/StringConstructors01/StringConstructors01.class new file mode 100644 index 0000000000000000000000000000000000000000..c4e2ce34c8353a953b7168f15c4f774be9ab10b7 GIT binary patch literal 1008 zcmZuwTTc@~7(LVO?kw9vhviaGQLCusT2Q=Dh>=uHhy@>TO%|TE?LropR`+8389w(9 z=&PF0M2weLf0X*oaud>IbLN}xHs3ij`}@z=?*JCCWS}1fj%zxu8%SYXLP5d}2{(I? z!z~>}xtZXYG>}0-$CQp~ju`{9C~?d&42(Nr=mwG3YKD)!(5d-ugMn=_Xv<#Hiykth zixV#yluE1NGUTdW(_N4EYHsjCCR1R~@tO?7#jWbD^VTW(PIITU5d~gzXGs?JZbVM~ z)td7<$>*5oxJ`32=*xBg=m=w@6$f?qsV5tb9u`+TVPb#*S=_^YhLO{%m1D|Jf}j=9Bn@wSyXMD|&EYcGZ3d19SuCP_ zW`gInUAG>QkX`6Aq_!#yL&fgOsKu>{REX2Mx+*QreG@x=c&_B|h@}a-l-wzaicdF3 zx;Na=3*5#DCz3mgDL~h@i2^-?etIxWj7T-eN`pxi35RJnMk`4Kb+QBYNhTsss3lH@ z9*kg=Y)WNCsNfX)CG>BqofZwtR)lBSs@S${O#&A+%hrW&*+LUBAs4PyJwVDf(;X;l z(&|86m+Le+%8In6I?&2$VsYL9FKeHnw=p`1y y9Ap1~Kt7+RMwd?nUPzP#`pw)vL>pZB044ne`sozMV$1F-QrSoHO0FbBUi}BKugVGl literal 0 HcmV?d00001 diff --git a/regression/strings/StringConstructors01/StringConstructors01.java b/regression/strings/StringConstructors01/StringConstructors01.java new file mode 100644 index 00000000000..406653de694 --- /dev/null +++ b/regression/strings/StringConstructors01/StringConstructors01.java @@ -0,0 +1,19 @@ +public class StringConstructors01 +{ + public static void main(String[] args) + { + char[] charArray = {'d', 'i', 'f', 'f', 'b', 'l', 'u', 'e'}; + String s = new String("test"); + + String s1 = new String(); + String s2 = new String(s); + String s3 = new String(charArray); + String s4 = new String(charArray, 4, 4); + + assert s1.equals(""); + assert s2.equals("test"); + assert s3.equals("diffblue"); + assert s4.equals("blue"); + } +} + diff --git a/regression/strings/StringConstructors01/test.desc b/regression/strings/StringConstructors01/test.desc new file mode 100644 index 00000000000..ed57bdfdde5 --- /dev/null +++ b/regression/strings/StringConstructors01/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringConstructors01.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/strings/StringConstructors02/StringConstructors02.class b/regression/strings/StringConstructors02/StringConstructors02.class new file mode 100644 index 0000000000000000000000000000000000000000..0cca7f99377fa26a1d5759ce91374e67278d1aea GIT binary patch literal 652 zcmZuv-%k@k5dP+R?Om@2Eu~H)P?s)4eX!QN}$N_l>jQ;DHCn z1lt}uSah&Nm|YP`B6X_bD0!h0F%0F1KnH}mcd+VX z4G;f6-^8qvU@;SUQ a9QzaO!Wrxd*o`CuQiSC{Gs5rWT+J(Rc7c@u literal 0 HcmV?d00001 diff --git a/regression/strings/StringConstructors02/StringConstructors02.java b/regression/strings/StringConstructors02/StringConstructors02.java new file mode 100644 index 00000000000..b20877b8106 --- /dev/null +++ b/regression/strings/StringConstructors02/StringConstructors02.java @@ -0,0 +1,9 @@ +public class StringConstructors02 +{ + public static void main(String[] args) + { + String s1 = new String(); + assert s1.equals(" "); + } +} + diff --git a/regression/strings/StringConstructors02/test.desc b/regression/strings/StringConstructors02/test.desc new file mode 100644 index 00000000000..c2a30b3534c --- /dev/null +++ b/regression/strings/StringConstructors02/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringConstructors02.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringConstructors03/StringConstructors03.class b/regression/strings/StringConstructors03/StringConstructors03.class new file mode 100644 index 0000000000000000000000000000000000000000..fba6b043267ffe1fb0c5a30968bb053eee927c71 GIT binary patch literal 713 zcmZuuT~8B16g{{5+3jM>Qn09~C~7~5n8+K%XsSLHeJC*jU)*jdWO3Qm*;#)~|A5bG zLK8{!-T$QV<7tlF8gV_v74i&;0uH{ReA}WO$v8dO(v5RN6-MuO!VhIVlOwp>QSuMm8)k)! z#LHMiEuXganTwJ|q%xU5di+qM`lzEpXk47Y%=2^hd+-(og4Lpm&si$#vq vK)=y-u*8Q$SI>!UmJERTz&l250>}Ie)A$B!hIvL(<5;NpPxUITa^&(~b%c;< literal 0 HcmV?d00001 diff --git a/regression/strings/StringConstructors03/StringConstructors03.java b/regression/strings/StringConstructors03/StringConstructors03.java new file mode 100644 index 00000000000..a2f6ced182a --- /dev/null +++ b/regression/strings/StringConstructors03/StringConstructors03.java @@ -0,0 +1,10 @@ +public class StringConstructors03 +{ + public static void main(String[] args) + { + String s = new String("test"); + String s2 = new String(s); + assert s2.equals("tesst"); + } +} + diff --git a/regression/strings/StringConstructors03/test.desc b/regression/strings/StringConstructors03/test.desc new file mode 100644 index 00000000000..5419e5ae48e --- /dev/null +++ b/regression/strings/StringConstructors03/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringConstructors03.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringConstructors04/StringConstructors04.class b/regression/strings/StringConstructors04/StringConstructors04.class new file mode 100644 index 0000000000000000000000000000000000000000..d7705f364f37fe5fe5d3d350a6b66c3325a6e54e GIT binary patch literal 736 zcmZuvT~8BH5IxiG?%i&Sy_AAQMMY6tAl8RI2{D?g2}#jlU6Z9x+xAKpm#yxHf5HF2 zAMjaCXd*`6{ZAU_7NKf2_p3* zJLs$UxdwCMzz-tALcQ17_uu->(2w?--82rOy$xMB(@p)st8M@F1TS!dha=dVgYb8M zr#s5xfqES1Zi^?CZ5}6$vq3tFlRK^3x^W5TP$tNKNp$>X2_?)B%zhYVs)Spp6KYfB zgHw%<;&>Djs{dmVXq2#uwZAx?_V?8wCFFW-f~fb}TU%O`rQT$Im=Nacf2ckIZ!~y& z4Evkr%}sbKFxWTIAqH6n@}$P0?V$F@Bjb+ literal 0 HcmV?d00001 diff --git a/regression/strings/StringConstructors04/StringConstructors04.java b/regression/strings/StringConstructors04/StringConstructors04.java new file mode 100644 index 00000000000..bd9828e6a5f --- /dev/null +++ b/regression/strings/StringConstructors04/StringConstructors04.java @@ -0,0 +1,10 @@ +public class StringConstructors04 +{ + public static void main(String[] args) + { + char[] charArray = {'d', 'i', 'f', 'f', 'b', 'l', 'u', 'e'}; + String s4 = new String(charArray, 4, 4); + assert s4.equals("bllue"); + } +} + diff --git a/regression/strings/StringConstructors04/test.desc b/regression/strings/StringConstructors04/test.desc new file mode 100644 index 00000000000..21394f70327 --- /dev/null +++ b/regression/strings/StringConstructors04/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringConstructors04.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringConstructors05/StringConstructors05.class b/regression/strings/StringConstructors05/StringConstructors05.class new file mode 100644 index 0000000000000000000000000000000000000000..8339e1ddab342a080fd8c8be285bde13134446f3 GIT binary patch literal 736 zcmZuvO>fgc5Ph52UdM6CHcd+k6etu(+KO-}5>hJ!3UEpZQZSO6lVfixx2^;J;2-cO z@&`BrQX^3Wcm5NI*_1YbxXkX(zM1#l?0*0G`73}eY+5Me631l=1zahigcTE4)!`b) zbqicwu3ET(n;dHl3u|7Q$|MU%arz`oy+I@c2DZmw?1XWcJ!B|0ny(nN_9&1Hl};GT z=lRh{+UI|trduN8Umeyf)yVZ6Vs3g>#6=O6BRucvs9TO^Lb-0`E| z{jJ_8Pki|-RNa7f@jk|B|TuZ5uY`7)n7n93Bp$T-vyU z219*@ethQhX_AZ*hT8v_IGQ%rvGEsAcW@y6jG@qPGw6+eTiG(?o7{_1hQ-DozE7ds zO`2b2M%|8R$TXrrrePw3b0svHET;>a@E%s_t;+O!@OZ_6qtA8WjUCg!x5xiz0AbO@xlCi=pEhDsVAyTvJ4jD-4lSVpik9>i5g|fU_a31Smaou o)Wvi4TT_|9e6@58YYeWvhgSRqZPxS5iRz=HU_VlR>r=|*UmKy5;Q#;t literal 0 HcmV?d00001 diff --git a/regression/strings/StringConstructors05/StringConstructors05.java b/regression/strings/StringConstructors05/StringConstructors05.java new file mode 100644 index 00000000000..49cc43f4269 --- /dev/null +++ b/regression/strings/StringConstructors05/StringConstructors05.java @@ -0,0 +1,10 @@ +public class StringConstructors05 +{ + public static void main(String[] args) + { + char[] charArray = {'d', 'i', 'f', 'f', 'b', 'l', 'u', 'e'}; + String s3 = new String(charArray); + assert s3.equals("diffkblue"); + } +} + diff --git a/regression/strings/StringConstructors05/test.desc b/regression/strings/StringConstructors05/test.desc new file mode 100644 index 00000000000..9804850d77e --- /dev/null +++ b/regression/strings/StringConstructors05/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringConstructors05.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring From f0cffa69e29879074adb565d01b6346d395bde9e Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Wed, 22 Feb 2017 14:23:22 +0000 Subject: [PATCH 012/699] =?UTF-8?q?=C2=A0added=20string=20searching=20meth?= =?UTF-8?q?ods=20indexOf=20and=20lastIndexOf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucas Cordeiro --- .../StringIndexMethods01.class | Bin 0 -> 1181 bytes .../StringIndexMethods01.java | 20 ++++++++++++++++++ .../strings/StringIndexMethods01/test.desc | 8 +++++++ .../StringIndexMethods02.class | Bin 0 -> 666 bytes .../StringIndexMethods02.java | 8 +++++++ .../strings/StringIndexMethods02/test.desc | 8 +++++++ .../StringIndexMethods03.class | Bin 0 -> 667 bytes .../StringIndexMethods03.java | 8 +++++++ .../strings/StringIndexMethods03/test.desc | 8 +++++++ .../StringIndexMethods04.class | Bin 0 -> 695 bytes .../StringIndexMethods04.java | 8 +++++++ .../strings/StringIndexMethods04/test.desc | 8 +++++++ .../StringIndexMethods05.class | Bin 0 -> 701 bytes .../StringIndexMethods05.java | 8 +++++++ .../strings/StringIndexMethods05/test.desc | 8 +++++++ 15 files changed, 92 insertions(+) create mode 100644 regression/strings/StringIndexMethods01/StringIndexMethods01.class create mode 100644 regression/strings/StringIndexMethods01/StringIndexMethods01.java create mode 100644 regression/strings/StringIndexMethods01/test.desc create mode 100644 regression/strings/StringIndexMethods02/StringIndexMethods02.class create mode 100644 regression/strings/StringIndexMethods02/StringIndexMethods02.java create mode 100644 regression/strings/StringIndexMethods02/test.desc create mode 100644 regression/strings/StringIndexMethods03/StringIndexMethods03.class create mode 100644 regression/strings/StringIndexMethods03/StringIndexMethods03.java create mode 100644 regression/strings/StringIndexMethods03/test.desc create mode 100644 regression/strings/StringIndexMethods04/StringIndexMethods04.class create mode 100644 regression/strings/StringIndexMethods04/StringIndexMethods04.java create mode 100644 regression/strings/StringIndexMethods04/test.desc create mode 100644 regression/strings/StringIndexMethods05/StringIndexMethods05.class create mode 100644 regression/strings/StringIndexMethods05/StringIndexMethods05.java create mode 100644 regression/strings/StringIndexMethods05/test.desc diff --git a/regression/strings/StringIndexMethods01/StringIndexMethods01.class b/regression/strings/StringIndexMethods01/StringIndexMethods01.class new file mode 100644 index 0000000000000000000000000000000000000000..f8086f133e6a279bb2247de2ef88906628d9fe73 GIT binary patch literal 1181 zcmZuv%Wl(95Ir}K+I1Y_IBnvT7AUlkHqZz3-SScaDN;)pMM#v@jeS#GQU}=%V#`k; zwHubKDN-td1bZZYgRelqT$eT?iDb>#bLN~oK6AhS{`?id9PVn!VN}KCeq?b)!x+XD zT-A`osQkDlLrI1S6_YZTWw@^5hRjnkOskktFstDvZYh{!$c^zJ5Ps-3yx@Tw@M>K+ z3~Yy?Z_V}G@D4+~H1U)nvEFb5LuSME#N+0ERrpV2GXeYD^%(M{=No(cHJ`3?Z+Ch- z^j&XvRT9(NA-7*{@>fy6f_VmY&946w*R~r?-xiNtDOEh7RXj($*%aZ6h7-)pPDxcA zc@!ANc{6P6^U$?J5rj4m#IEp!PlblZL&vSvs`aMOF@QljNXG&e8LakL_fP-zq3<_* zi7)9`#-a>MG*??;0V@(-WzgD3$Tli3%X0tOC=3I==2oz#<2J}ZqdmY@bx+vgf29*H zgW}5H-l~zKrOHHwAz7+KIaTLD7)H)7MEUpjJl&t}mQ3H)um) zlK|TE4o2y6<>782HJEF!Y z&ziA~Bg7ApFB^6X2}6C4)E6Y59i#8tDZmpgC|$r{*%%{6tOtRVR3qI9SY?A7#TNRF zd?$3GrS{M=wH8vwNGHK6o0_4tpm#(0vYD2gY$t~R5&UBNl&H5sX37%Jw;;7w?#A%(Zlaey?AsOJYV_z44lkYz=fY=(9?Ow1hgUl>*} zVil|*dMvA$Cz%Up>zs@B24u}_3+5q|#0MnepAc`)aJpKlmqbjzCojOoXv9l@0fmtI AQUCw| literal 0 HcmV?d00001 diff --git a/regression/strings/StringIndexMethods01/StringIndexMethods01.java b/regression/strings/StringIndexMethods01/StringIndexMethods01.java new file mode 100644 index 00000000000..da000057993 --- /dev/null +++ b/regression/strings/StringIndexMethods01/StringIndexMethods01.java @@ -0,0 +1,20 @@ +public class StringIndexMethods01 +{ + public static void main(String[] args) + { + String letters = "automatictestcasegenerationatdiffblue"; + + assert letters.indexOf('c')==8; + assert letters.indexOf('a', 1)==5; + assert letters.indexOf('$')==-1; + assert letters.lastIndexOf('c')==13; + assert letters.lastIndexOf('a', 25)==22; + assert letters.lastIndexOf('$')==-1; + assert letters.indexOf("diffblue")==29; + assert letters.indexOf("diffblue", 7)==29; + assert letters.indexOf("generation")==17; + assert letters.lastIndexOf("diffblue")==29; + assert letters.lastIndexOf("diffblue", 25)==-1; + assert letters.lastIndexOf("automatic")==0; + } +} diff --git a/regression/strings/StringIndexMethods01/test.desc b/regression/strings/StringIndexMethods01/test.desc new file mode 100644 index 00000000000..005d4459f12 --- /dev/null +++ b/regression/strings/StringIndexMethods01/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringIndexMethods01.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/strings/StringIndexMethods02/StringIndexMethods02.class b/regression/strings/StringIndexMethods02/StringIndexMethods02.class new file mode 100644 index 0000000000000000000000000000000000000000..fe322fde894d06c831a4097040b85f7f2dbd88f0 GIT binary patch literal 666 zcmZuu&rcIU6#ibfyVEWUl!COVMN!bAi5SC8Vl=2plOl&26Y(_Noz}tauGyV6{w-WQ zdR7xiG|{_%lQF(ogvP|ndvD&n@5j9P`TOg40Nc3fqmEV$?K%Wjd|bpOfy+Kzv;;an zR&hn(Dq(S5=DEs@PLuqx&gC#x5rGZ}-i}VRc|dTwn=c5}-852!`Myrnvtlw-*>gM0 z7Za%y!gBXj|4_b@Td_>WTLY8nWPINOX9q@xZ}#Nda$aDKP}>RPzvTWPEwWHO)s|}I z6xK^3^?py8*J+gBy?4j51_&@q*pP)uC(`K9sN94yS7Vi^j2mepO{7PoVO*#HK4w@b zz%^Vaw5PTnoxSx*mZceC>3@O(>j5@!gV2~F_lJinH2<_tu>_&5-~AE6?e=<`Jzmlj zw;S_*c{`EHb*7?o1H2Sd@C7gT0Bih5b^bPLw5@fn9FTo6$2mTAI1^|0)(Pm79mG6G zuWS-S8(84lj`kT^;k??c^gqKnLhE)zR*z9_cpotH4erYmct0#hrR137c_!xQv5Y{I wPc_glbOaW;S~@qeU8(^KO>vCc5k&PPs?HZUQ?fHdmc&IRcxY{3D7BXV0QGx_?EnA( literal 0 HcmV?d00001 diff --git a/regression/strings/StringIndexMethods02/StringIndexMethods02.java b/regression/strings/StringIndexMethods02/StringIndexMethods02.java new file mode 100644 index 00000000000..5c2ea999dd0 --- /dev/null +++ b/regression/strings/StringIndexMethods02/StringIndexMethods02.java @@ -0,0 +1,8 @@ +public class StringIndexMethods02 +{ + public static void main(String[] args) + { + String letters = "automatictestcasegenerationatdiffblue"; + assert letters.indexOf('a', 1)==6; + } +} diff --git a/regression/strings/StringIndexMethods02/test.desc b/regression/strings/StringIndexMethods02/test.desc new file mode 100644 index 00000000000..cad6c487fae --- /dev/null +++ b/regression/strings/StringIndexMethods02/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringIndexMethods02.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringIndexMethods03/StringIndexMethods03.class b/regression/strings/StringIndexMethods03/StringIndexMethods03.class new file mode 100644 index 0000000000000000000000000000000000000000..e8733f571683a9351d676f8865818ef6c30d224d GIT binary patch literal 667 zcmZuv-)j>=5dJ22$t9O-o2I`~+ghusrV3WDZx&IiLL{{h5yASjx!c68mpi%L6aSXJ z_~^3=Ehy-_f0Kx_SKA=S!tCtKeBXRKyFY(_{SIIUH+56eC-Va3C$k201# ztogW%bq`kvb8Vru%#2DC{YYssh-E~eLqcU&CCc0ROPi15w6cw5wa*dSDQ!}u?`-%s-_luwkU zT0VnylSsbbm*#aE={t9CTh;&prU;uNH|bay6&k5cD6|~OL}naF6Ja7X91h}K2Jlhm zMggwk8lg3j_3-?zkFzYz2=o7I=%F286W0li3G!fYBt!F0=nPA!$3mMz^TCkE(dlk= zc}^4P9_KX=D3V%bGP=;fb1^w5c)o|&;Ag7w%Tc3c)wAb-?4{XG^J$HD;=O$H6!gg! zVuo#{2oggZm}TFVK1GQau-Yv3KEpZ2!mUR81g`r5^=~M@JVoV)WhfO4)7*$@*;cT^ yBAR@vf_~ZmGRNNhg@m1=7ckrOPEb9D=YE9ie1S6|JC|cg$|wa7tmuWJ*Ww>}&57Rt literal 0 HcmV?d00001 diff --git a/regression/strings/StringIndexMethods03/StringIndexMethods03.java b/regression/strings/StringIndexMethods03/StringIndexMethods03.java new file mode 100644 index 00000000000..83b710073b5 --- /dev/null +++ b/regression/strings/StringIndexMethods03/StringIndexMethods03.java @@ -0,0 +1,8 @@ +public class StringIndexMethods03 +{ + public static void main(String[] args) + { + String letters = "automatictestcasegenerationatdiffblue"; + assert letters.lastIndexOf('$')==1; + } +} diff --git a/regression/strings/StringIndexMethods03/test.desc b/regression/strings/StringIndexMethods03/test.desc new file mode 100644 index 00000000000..3dff0b27714 --- /dev/null +++ b/regression/strings/StringIndexMethods03/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringIndexMethods03.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringIndexMethods04/StringIndexMethods04.class b/regression/strings/StringIndexMethods04/StringIndexMethods04.class new file mode 100644 index 0000000000000000000000000000000000000000..69a8fe4d628343caa7e78dbb94db2c2836b7591c GIT binary patch literal 695 zcmZuv!EVz)5PcITw&S{KnzkW@6liH71&MOVjS7JZNEInPq(Y)SZR}0h;@HSuBfg~< zj+_Chl|X_!--HmeE@^~RS(=^Moq6x=TmSm=?FWD^Ha&P~xmd2k#Z?#AJhZXm;JODJ zEeAI|+{CJbHNwKW$TFE~mBiUom5D(lLjoNV>}?e*{fJ<7HeV6SJ4q-Bb3GNym-%=g z(*x7Y2VDv?CMjX@GHwUAecVBZP@hij4~}J^|JypBB{<4R-yaf| zI+wVy%l=Jqb|SW(jSFR_QW;(dV!w3G2kiSHR`~@zepITr%&j=Hz@DPUagM7MUWwPr z-80Z<(}+4pyVxXDF^>l4ru79%{P9Sm)cXSK1kHPm@+m6y_D9TohyD5t&QAkTDj;gi z#JC)7{(BrOaOHx2qwQdkv!x3S-GU65Z@8zZp1>)8LfQHXYYH~eV?Zh>`Hzk2X2Esk EFZ08aZ~y=R literal 0 HcmV?d00001 diff --git a/regression/strings/StringIndexMethods04/StringIndexMethods04.java b/regression/strings/StringIndexMethods04/StringIndexMethods04.java new file mode 100644 index 00000000000..1271bcaf36b --- /dev/null +++ b/regression/strings/StringIndexMethods04/StringIndexMethods04.java @@ -0,0 +1,8 @@ +public class StringIndexMethods04 +{ + public static void main(String[] args) + { + String letters = "automatictestcasegenerationatdiffblue"; + assert letters.indexOf("diffblue")==28; + } +} diff --git a/regression/strings/StringIndexMethods04/test.desc b/regression/strings/StringIndexMethods04/test.desc new file mode 100644 index 00000000000..758f22d2bf4 --- /dev/null +++ b/regression/strings/StringIndexMethods04/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringIndexMethods04.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringIndexMethods05/StringIndexMethods05.class b/regression/strings/StringIndexMethods05/StringIndexMethods05.class new file mode 100644 index 0000000000000000000000000000000000000000..a4f4f7674958e1569272f8ec1afd17e2acd9bfb2 GIT binary patch literal 701 zcmZuv&rcIU6#k~W-Q8}NQVK$=f}kL+CgK545~D#)niM&dn1HA0?z9eWcgfDI@o(Yc z(X*OBqKV%9n~d?zVrh(C-miJ@`@VTIKYo4r24EW>fxG?>sWTN;=@7H z#SI^;SaWfcVSb$}B{D73L_L*?4`LB9up^feFP?D3PL-^DEkZzqiZfcyP4&qDEB z8mQLAST~8pyFH;_r;)n<;GRJZFoPPy2G4am=30hYC>?SoMj{az71D(3NDhaCI2Qq` z2#95p6K8;RY%nyZ3ZG1_{VdDUjA7w_+%9eh*hHJ5KAqej9E(u@Rl1mEsK#9BLjL~H ztmNN~bUR&I;uLI`CKR{8*>SUdw$WXx?8Wfw>9*vgBuQW=%Pq0q0bhlyGTW2WS?@|2<=kOfvcY{$X zFly9Kz+@ewaWPMs2lmr^rv-|xT#DE(*nqi)cZSL-T>ArT>ocq=*hG*4DWeoTHnJBB GuBG4EL6lnn literal 0 HcmV?d00001 diff --git a/regression/strings/StringIndexMethods05/StringIndexMethods05.java b/regression/strings/StringIndexMethods05/StringIndexMethods05.java new file mode 100644 index 00000000000..f6de4ce541b --- /dev/null +++ b/regression/strings/StringIndexMethods05/StringIndexMethods05.java @@ -0,0 +1,8 @@ +public class StringIndexMethods05 +{ + public static void main(String[] args) + { + String letters = "automatictestcasegenerationatdiffblue"; + assert letters.lastIndexOf("diffblue", 25)==1; + } +} diff --git a/regression/strings/StringIndexMethods05/test.desc b/regression/strings/StringIndexMethods05/test.desc new file mode 100644 index 00000000000..d415ef1381e --- /dev/null +++ b/regression/strings/StringIndexMethods05/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringIndexMethods05.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring From b5d6a133e3957e1b0d9b2ed230f6327b18e5e5f8 Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Wed, 22 Feb 2017 14:24:07 +0000 Subject: [PATCH 013/699] =?UTF-8?q?=C2=A0added=20string=20methods=20length?= =?UTF-8?q?,=20position,=20replace,=20toUpperCase,=20toLowerCase,=20and=20?= =?UTF-8?q?trim?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucas Cordeiro --- .../StringMiscellaneous01.class | Bin 0 -> 1382 bytes .../StringMiscellaneous01.java | 32 ++++++++++++++ .../strings/StringMiscellaneous01/test.desc | 8 ++++ .../StringMiscellaneous02.class | Bin 0 -> 650 bytes .../StringMiscellaneous02.java | 8 ++++ .../strings/StringMiscellaneous02/test.desc | 8 ++++ .../StringMiscellaneous03.class | Bin 0 -> 821 bytes .../StringMiscellaneous03.java | 15 +++++++ .../strings/StringMiscellaneous03/test.desc | 8 ++++ .../StringMiscellaneous04.class | Bin 0 -> 1733 bytes .../StringMiscellaneous04.java | 40 ++++++++++++++++++ .../strings/StringMiscellaneous04/test.desc | 8 ++++ 12 files changed, 127 insertions(+) create mode 100644 regression/strings/StringMiscellaneous01/StringMiscellaneous01.class create mode 100644 regression/strings/StringMiscellaneous01/StringMiscellaneous01.java create mode 100644 regression/strings/StringMiscellaneous01/test.desc create mode 100644 regression/strings/StringMiscellaneous02/StringMiscellaneous02.class create mode 100644 regression/strings/StringMiscellaneous02/StringMiscellaneous02.java create mode 100644 regression/strings/StringMiscellaneous02/test.desc create mode 100644 regression/strings/StringMiscellaneous03/StringMiscellaneous03.class create mode 100644 regression/strings/StringMiscellaneous03/StringMiscellaneous03.java create mode 100644 regression/strings/StringMiscellaneous03/test.desc create mode 100644 regression/strings/StringMiscellaneous04/StringMiscellaneous04.class create mode 100644 regression/strings/StringMiscellaneous04/StringMiscellaneous04.java create mode 100644 regression/strings/StringMiscellaneous04/test.desc diff --git a/regression/strings/StringMiscellaneous01/StringMiscellaneous01.class b/regression/strings/StringMiscellaneous01/StringMiscellaneous01.class new file mode 100644 index 0000000000000000000000000000000000000000..4f63b35324bc7a9d90f2659386560f3732184be5 GIT binary patch literal 1382 zcmZux-*XdH6#j1Z$K7lfnx<^qRG~qrrW9Jx5VfgFNufsj18GMG`n26#%R;it?A|cL zgEKzxSJVe*c8U)7_``BGnAuZL=Xt33{@Z_tmz5W2N3q^g$C zvQ)2c*6M1Qj1*m+zNSo`noW{@u&<9MjWi8pLnJ{g8V91%9LhF1Xr6E5G+mwnx>YPU zrpAF*8Yl;&^c*AWB)u8EjdM@Iep7)c(9=ve8L}A1d$gud_K>cgO}= 0; count--) + { + System.out.printf("%c ", s1.charAt(count)); + assert s1.charAt(count) == s2.charAt(i); + ++i; + } + + // copy characters from string into charArray + s1.getChars(0, 5, charArray, 0); + i=0; + for (char character : charArray) + { + System.out.print(character); + assert s3.charAt(i) == character; + ++i; + } + + System.out.println(); + } +} diff --git a/regression/strings/StringMiscellaneous01/test.desc b/regression/strings/StringMiscellaneous01/test.desc new file mode 100644 index 00000000000..050c3e99e90 --- /dev/null +++ b/regression/strings/StringMiscellaneous01/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringMiscellaneous01.class +--string-refine --unwind 30 +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/strings/StringMiscellaneous02/StringMiscellaneous02.class b/regression/strings/StringMiscellaneous02/StringMiscellaneous02.class new file mode 100644 index 0000000000000000000000000000000000000000..f1d880c012a9bca0bd88834aef0e69b29beb6655 GIT binary patch literal 650 zcmZuvT~8B16g{`wcG_iuQoc$NErN=gh%vlLj08VIQuLw3M0}cVCuMLuYi4KtF}(Qb zvzkDniN5=rjPcGQG$v+~JNM4qbMBcl`}6nL?*O)ND?}ZOHMHswSPId`vcQ!P6)Xy@ zgt&@p0v*Eay38_VolZ^mL}#*}r~!cv3Ds?Fw0lGdHg3Nnly}pCB20I+Q7`gQU)clS z%m*W>4Pjy9P4`&7mz#++!_A(v+6*6h;AGFq`0c)YSM&?45^CFV@|Qg9rMZpOGwrF` z=dgX9#VTPQmFC&~2lqT}gb0&_rJdZRBk6S9IZ&DFJXc0pE>jaB#00ZPxQ;bKYpiAG z;(|}DO)X*mzf%O(Biz7ELSqbl**{jX`)BJM%=RS84Bb&-&mQ|S2JI$nDH}3SnYLKSEOkF4IKkZAQmG?6PcyQmF;3g4PP9mKvLyXk$vyHcg;DKum0(mSsY>F1u!T)-UK+ z;EQj4Ruh`2(RaVVZ}CCAyR{`IO(rw<&fI&>nKSeA&zJ82HtwIo97{Z7h*zqw7^J4# z=M3qV&$}g)(xEGY2Jz}xK~0B_86B&5z_2it+_>=Jh3B~*L+(l$ z3f6SgvCfd0w!Z8gb5oF+S6J|0;W;Ej?664&+uRw5qsZVrO3fp~YY>W5*{jlVdWzq) z>5<6dKKCt;_b-)_vm&4adZ7c9>7i5f2UunyydXt!u+T4>Gn6gT%4n5W&cHr~g_xx| z5p6PR&SH+@uyjPN30fQ3SSuTEtKa1P_@-1FLz4QNa!!7a>LQ6SBaN$(Siw@K}FswyHrK@JH8 zIR*34xWPzz`8PGGSh&2>Mx-5>%_hgtMo^?vNb%2*r@R-}3vp${^zG1ud?c&z7nhHw AM*si- literal 0 HcmV?d00001 diff --git a/regression/strings/StringMiscellaneous03/StringMiscellaneous03.java b/regression/strings/StringMiscellaneous03/StringMiscellaneous03.java new file mode 100644 index 00000000000..2adfe30f5d0 --- /dev/null +++ b/regression/strings/StringMiscellaneous03/StringMiscellaneous03.java @@ -0,0 +1,15 @@ +public class StringMiscellaneous03 +{ + public static void main(String[] args) + { + String s1 = "Automatic Test Generation"; + String s2 = "noitareneG tseT citamotuA"; + char[] charArray = new char[5]; + int i=0; + for (int count = s1.length() - 1; count >= 0; count--) + { + assert s1.charAt(count) != s2.charAt(i); + ++i; + } + } +} diff --git a/regression/strings/StringMiscellaneous03/test.desc b/regression/strings/StringMiscellaneous03/test.desc new file mode 100644 index 00000000000..f255272ed5b --- /dev/null +++ b/regression/strings/StringMiscellaneous03/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringMiscellaneous03.class +--string-refine --unwind 30 +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringMiscellaneous04/StringMiscellaneous04.class b/regression/strings/StringMiscellaneous04/StringMiscellaneous04.class new file mode 100644 index 0000000000000000000000000000000000000000..c7f02bedbb23ef52f70e38b64db6957dcab1859a GIT binary patch literal 1733 zcmZ`(O;cM{7=BK^&ducl>4i{&qSt;U;iG_Jus~~RNGcjaB|ruIx+Ev`Vo2h>H+H)3 z!j(UOjWaIVjT`GsI-_IVxa!iM;L4>lZac;I-0+cfaFWS+&v`%2bDsBk^Zey6&j3uL zq@oL>3dR(SE4UiQ5GGViVv6H!6&#~syn|^4?{cK%`HYJ9a81Fi+{`JMm+N%}H{|-h zf}3((P;g7erR8Q(S{aV4ire^rq3@FEIKpwG<3o;*7?k;9<>(5vP;1ylk+o#Op;q#;&m7}0x4eK7j zY*qr)uz|a@UtG#&Z{^lA8a|Qx9#=T-uBZyzl+0_`l&9en+#0s9O-wjbhUpllQM_l` zX3-V4VcNF&z_?D&`V^mO_#9to_)>BbJ(D#K;%o=S4#=%Y>iroVWAJUKsrlmThFNi_ zY@)5Jt+&o4NgZtr6dpLP*e9LT8ZITY;;q`m9g=`ccL{TUj)B`PR;5zX>112g790xc z^H}Z7Bq()Rr_3B2QatzKD>Ny+r{YOhX!?kel5i|rlui^$ zBjYy6L8G^Yx9DG>i~b&1WKe3EEI*hW1o|~-H%u#|H8}DV>?bl9r2rxCkW_^WxJb4E z__mI@Bsazy03}Q0lIz#-+T(?_tx>4?mz2zTo1f@9M;vqZ|K_e zk4DOoY!h0ciSE0{o7sR@FB%KzJ)N1OP4u>TBc0x{CeF2a^-k}26Mb#o{!TAdj?M<3 zAgm8Gao(Q_#e%au#-F7We<~aeN0lEi9^=vQbV~KWosX)zFB)oM@cUC59){S%FnfIX zC)H^pCdu`AVh;iyfh(4T14imvDW{BQAx@j(ZXzaRCMlb4!;9KbU4t;opD1O8M z{=gufBZj}IqkmHe|DkUF3xjpz0*m7!8zFlVS6B*hT%wycpuU8`ak=#!7=^D{!Iu7bpgj;1}q0O$0fCSE%L4?IS||1*N8&py_a RgcO8NyD62Iq>T?F{{f+OeIx(? literal 0 HcmV?d00001 diff --git a/regression/strings/StringMiscellaneous04/StringMiscellaneous04.java b/regression/strings/StringMiscellaneous04/StringMiscellaneous04.java new file mode 100644 index 00000000000..e9fe0292317 --- /dev/null +++ b/regression/strings/StringMiscellaneous04/StringMiscellaneous04.java @@ -0,0 +1,40 @@ +public class StringMiscellaneous04 +{ + public static void main(String[] args) + { + String s1 = "diffblue"; + String s2 = "TESTGENERATION"; + String s3 = " automated "; + + assert s1.equals("diffblue"); + assert s2.equals("TESTGENERATION"); + assert s3.equals(" automated "); + + System.out.printf( + "Replace 'f' with 'F' in s1: %s\n\n", s1.replace('f', 'F')); + String tmp=s1.replace('f', 'F'); + assert tmp.equals("diFFblue"); + + tmp=s1.toUpperCase(); + assert tmp.equals("DIFFBLUE"); + + tmp=s2.toLowerCase(); + assert tmp.equals("testgeneration"); + + tmp=s3.trim(); + assert tmp.equals("automated"); + + // test toCharArray method + char[] charArray = s1.toCharArray(); + System.out.print("s1 as a character array = "); + + int i=0; + for (char character : charArray) + { + assert character=="diffblue".charAt(i); + ++i; + } + + System.out.println(); + } +} diff --git a/regression/strings/StringMiscellaneous04/test.desc b/regression/strings/StringMiscellaneous04/test.desc new file mode 100644 index 00000000000..737ab3b0f8c --- /dev/null +++ b/regression/strings/StringMiscellaneous04/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringMiscellaneous04.class +--string-refine --unwind 30 +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring From ccf841023104395719722775ab7fa3ddc047a81d Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Wed, 22 Feb 2017 14:24:57 +0000 Subject: [PATCH 014/699] =?UTF-8?q?=C2=A0added=20test=20cases=20related=20?= =?UTF-8?q?to=20string=20startsWith=20and=20endsWith?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucas Cordeiro --- .../StringStartEnd01/StringStartEnd01.class | Bin 0 -> 1082 bytes .../StringStartEnd01/StringStartEnd01.java | 31 ++++++++++++++++++ regression/strings/StringStartEnd01/test.desc | 8 +++++ .../StringStartEnd02/StringStartEnd02.class | Bin 0 -> 810 bytes .../StringStartEnd02/StringStartEnd02.java | 15 +++++++++ regression/strings/StringStartEnd02/test.desc | 8 +++++ .../StringStartEnd03/StringStartEnd03.class | Bin 0 -> 808 bytes .../StringStartEnd03/StringStartEnd03.java | 15 +++++++++ regression/strings/StringStartEnd03/test.desc | 8 +++++ 9 files changed, 85 insertions(+) create mode 100644 regression/strings/StringStartEnd01/StringStartEnd01.class create mode 100644 regression/strings/StringStartEnd01/StringStartEnd01.java create mode 100644 regression/strings/StringStartEnd01/test.desc create mode 100644 regression/strings/StringStartEnd02/StringStartEnd02.class create mode 100644 regression/strings/StringStartEnd02/StringStartEnd02.java create mode 100644 regression/strings/StringStartEnd02/test.desc create mode 100644 regression/strings/StringStartEnd03/StringStartEnd03.class create mode 100644 regression/strings/StringStartEnd03/StringStartEnd03.java create mode 100644 regression/strings/StringStartEnd03/test.desc diff --git a/regression/strings/StringStartEnd01/StringStartEnd01.class b/regression/strings/StringStartEnd01/StringStartEnd01.class new file mode 100644 index 0000000000000000000000000000000000000000..37d2596a6c101908d347169dcc750faae76deffd GIT binary patch literal 1082 zcmaJ=O-~bH5PshM?y}gj*a`>;idsNEt*C%R1DKc~Ca#ebPuuPW7t5CHE*?xg$!{>q z#l#CY6E!JDBF3v{{R8?ZJc0ABKr1#T?Y{HQ%ri63GrM1RKkfj?VO)oaE*0GxPHQ-$ zp-0164d-+SIG;cYSrxrHbaZLx)Avx#y?)=(H!42;5WD2a8 zqQLW)COELsitOT}+xBXluVR!zn=F?0i|bZ-EhxG-JzgsP2S$J(n)RLGkwIS3KpGi_ z)Y0lRV&sMqpI7AuH6+(6=fhpxh+RVD8n}p@fo2?MXsOn@aX@`G2+9F5rD{C&5`*A6 z2F8%1zDI{raoNBXT>WdLJB4Mp7?GZJRAA6UPAOdQqKCvXTSq7oJX6PitCs?r>pT0{ zWOexI5)mYn{i}SOfpD z510N2uQoqcL9zy2uQ{hK#MJM`D#=7##Yt!wp-*T64VWT(28~!i5_wX!Ou9ZHO`nqe zj1+xNBE6srZ%D8Ygxn_k3+ej}opj@0tg(k4C@R|N$M~OwZ~X+P=;V!=iBX!xt;nAiwWAn literal 0 HcmV?d00001 diff --git a/regression/strings/StringStartEnd01/StringStartEnd01.java b/regression/strings/StringStartEnd01/StringStartEnd01.java new file mode 100644 index 00000000000..c1bc4bac328 --- /dev/null +++ b/regression/strings/StringStartEnd01/StringStartEnd01.java @@ -0,0 +1,31 @@ +public class StringStartEnd01 +{ + public static void main(String[] args) + { + String[] strings = {"tested", "testing", "passed", "passing"}; + + int i=0; + for (String string : strings) + { + if (string.startsWith("te")) + ++i; + } + assert i==2; + + i=0; + for (String string : strings) + { + if (string.startsWith("ste", 2)) + ++i; + } + assert i==1; + + i=0; + for (String string : strings) + { + if (string.endsWith("ed")) + ++i; + } + assert i==2; + } +} diff --git a/regression/strings/StringStartEnd01/test.desc b/regression/strings/StringStartEnd01/test.desc new file mode 100644 index 00000000000..a5463d5b5ea --- /dev/null +++ b/regression/strings/StringStartEnd01/test.desc @@ -0,0 +1,8 @@ +KNOWNBUG +StringStartEnd01.class +--string-refine --unwind 30 +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/strings/StringStartEnd02/StringStartEnd02.class b/regression/strings/StringStartEnd02/StringStartEnd02.class new file mode 100644 index 0000000000000000000000000000000000000000..f7b535e4848e94bf5bb0cddd7f7684014d04f7a7 GIT binary patch literal 810 zcmZuvO-~b16g_Xg-gG*pWw6*nQNgMOEJZ?C2oeq8s^Ve{P+U#h2@aMinR)dW@F!$r z;)abIHGxDU?)@A730LBMqtHl5X5PDV-?{hPbKd;;{pA$EJZ3Enpu{m|;)aQvCT^J+ zH!)#B!R-`mlsWELuq5WLg?p%QOfn3Wy*TzG5p=_NHHf`t$8R&RZ3bg02m`UqpjIX~ z7_^mc+h@qugV0~^?KS=Ag#^>Vo)?4+!v-W#%@t7)?kvi}j4Qm>>u276 zg6EiGFqc}Lf6Xno+lyNM(?GV$|1G0}NUVkJ*|{0n(Z(PghTP@uG@|fhA?M{XAVNy* zOFc3rgCwO0-^MiV+sGovQ0Vu0axQ%>in&au6Y@6OpJAm#bCP{+KMo?leK8W5AbNB_?r&q9?r(sundJ&n1Vt*Cw1w6o z`WmC1(XLOOfPIueT%*-Uk_;*2F-)<9et-r}`xgHOrJ*{i+t3`%ZRn2fHVnsb>*}NF z_3G(@rY`7tJ+Hk-shZd49vVf%;m0uF!Z=XafzFQ3ettsg5V?}}4(YG38Yf79m+VTy zJ^_QL;*(w32AqR~IMny)k2wniD07UPxMJd}iEAb% zOiWr(a6JPX6^UJx=2S6?=^y*FOHF+{A0Ye&X$> zc#dfXbE)0=*W7Zuy{Ii72eMW1Zy6Ot$y(^o-J6viZ4AO;D4g$3BPJqF74MY|sJvt!oH!(rCH$a!n3L{biMJkvyh1MbZ z8mFDnu1_Cg$LOtFN1fCf(c3;qpCQ*~6gsX3b4)E(Vz8jj&M)CV)` zwc`a%UC@hqQG1Vat*GCcZ=kgR literal 0 HcmV?d00001 diff --git a/regression/strings/StringStartEnd03/StringStartEnd03.java b/regression/strings/StringStartEnd03/StringStartEnd03.java new file mode 100644 index 00000000000..79479f9535b --- /dev/null +++ b/regression/strings/StringStartEnd03/StringStartEnd03.java @@ -0,0 +1,15 @@ +public class StringStartEnd03 +{ + public static void main(String[] args) + { + String[] strings = {"tested", "testing", "passed", "passing"}; + + int i=0; + for (String string : strings) + { + if (string.endsWith("ed")) + ++i; + } + assert i==3; + } +} diff --git a/regression/strings/StringStartEnd03/test.desc b/regression/strings/StringStartEnd03/test.desc new file mode 100644 index 00000000000..e6d8c460709 --- /dev/null +++ b/regression/strings/StringStartEnd03/test.desc @@ -0,0 +1,8 @@ +KNOWNBUG +StringStartEnd03.class +--string-refine --unwind 15 +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring From 846f168afca388414ab315eae1c5d1db83c39566 Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Wed, 22 Feb 2017 14:25:48 +0000 Subject: [PATCH 015/699] =?UTF-8?q?=C2=A0added=20test=20cases=20related=20?= =?UTF-8?q?to=20string=20valueOf=20methods?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucas Cordeiro --- .../StringValueOf01/StringValueOf01.class | Bin 0 -> 1565 bytes .../StringValueOf01/StringValueOf01.java | 41 ++++++++++++++++++ regression/strings/StringValueOf01/test.desc | 8 ++++ .../StringValueOf02/StringValueOf02.class | Bin 0 -> 749 bytes .../StringValueOf02/StringValueOf02.java | 9 ++++ regression/strings/StringValueOf02/test.desc | 8 ++++ .../StringValueOf03/StringValueOf03.class | Bin 0 -> 748 bytes .../StringValueOf03/StringValueOf03.java | 9 ++++ regression/strings/StringValueOf03/test.desc | 8 ++++ .../StringValueOf04/StringValueOf04.class | Bin 0 -> 688 bytes .../StringValueOf04/StringValueOf04.java | 9 ++++ regression/strings/StringValueOf04/test.desc | 8 ++++ .../StringValueOf05/StringValueOf05.class | Bin 0 -> 686 bytes .../StringValueOf05/StringValueOf05.java | 9 ++++ regression/strings/StringValueOf05/test.desc | 8 ++++ .../StringValueOf06/StringValueOf06.class | Bin 0 -> 687 bytes .../StringValueOf06/StringValueOf06.java | 9 ++++ regression/strings/StringValueOf06/test.desc | 8 ++++ .../StringValueOf07/StringValueOf07.class | Bin 0 -> 916 bytes .../StringValueOf07/StringValueOf07.java | 10 +++++ regression/strings/StringValueOf07/test.desc | 8 ++++ .../StringValueOf08/StringValueOf08.class | Bin 0 -> 694 bytes .../StringValueOf08/StringValueOf08.java | 9 ++++ regression/strings/StringValueOf08/test.desc | 8 ++++ .../StringValueOf09/StringValueOf09.class | Bin 0 -> 702 bytes .../StringValueOf09/StringValueOf09.java | 9 ++++ regression/strings/StringValueOf09/test.desc | 8 ++++ .../StringValueOf10/StringValueOf10.class | Bin 0 -> 722 bytes .../StringValueOf10/StringValueOf10.java | 9 ++++ regression/strings/StringValueOf10/test.desc | 8 ++++ 30 files changed, 203 insertions(+) create mode 100644 regression/strings/StringValueOf01/StringValueOf01.class create mode 100644 regression/strings/StringValueOf01/StringValueOf01.java create mode 100644 regression/strings/StringValueOf01/test.desc create mode 100644 regression/strings/StringValueOf02/StringValueOf02.class create mode 100644 regression/strings/StringValueOf02/StringValueOf02.java create mode 100644 regression/strings/StringValueOf02/test.desc create mode 100644 regression/strings/StringValueOf03/StringValueOf03.class create mode 100644 regression/strings/StringValueOf03/StringValueOf03.java create mode 100644 regression/strings/StringValueOf03/test.desc create mode 100644 regression/strings/StringValueOf04/StringValueOf04.class create mode 100644 regression/strings/StringValueOf04/StringValueOf04.java create mode 100644 regression/strings/StringValueOf04/test.desc create mode 100644 regression/strings/StringValueOf05/StringValueOf05.class create mode 100644 regression/strings/StringValueOf05/StringValueOf05.java create mode 100644 regression/strings/StringValueOf05/test.desc create mode 100644 regression/strings/StringValueOf06/StringValueOf06.class create mode 100644 regression/strings/StringValueOf06/StringValueOf06.java create mode 100644 regression/strings/StringValueOf06/test.desc create mode 100644 regression/strings/StringValueOf07/StringValueOf07.class create mode 100644 regression/strings/StringValueOf07/StringValueOf07.java create mode 100644 regression/strings/StringValueOf07/test.desc create mode 100644 regression/strings/StringValueOf08/StringValueOf08.class create mode 100644 regression/strings/StringValueOf08/StringValueOf08.java create mode 100644 regression/strings/StringValueOf08/test.desc create mode 100644 regression/strings/StringValueOf09/StringValueOf09.class create mode 100644 regression/strings/StringValueOf09/StringValueOf09.java create mode 100644 regression/strings/StringValueOf09/test.desc create mode 100644 regression/strings/StringValueOf10/StringValueOf10.class create mode 100644 regression/strings/StringValueOf10/StringValueOf10.java create mode 100644 regression/strings/StringValueOf10/test.desc diff --git a/regression/strings/StringValueOf01/StringValueOf01.class b/regression/strings/StringValueOf01/StringValueOf01.class new file mode 100644 index 0000000000000000000000000000000000000000..8103d7fb901728c98fd932908491f85aef3bfe16 GIT binary patch literal 1565 zcmZ`(TXzdl6#h;!lQWrwP9tekq!+4Er57o!-lS5cRV|tzEsIGrVThDm`Wrm?0e$ht zT9y}=RkN^o@nG>Yc=98#PkNgnomuPbea^SN< z83hSJCls6&bduwoiu0J_m}c11u9r$iv1~3EN)u*D&*Y6P16yG5jF<(pJjURTc3x$W z63bbGp>D=37_*fJ8KamK!UR0f%>qM1baCdMzM}W!^}?N=`Et=L+!+>%yXMRK(*2A2 z!>T;T1&$eV&2f=I8ClA2cv0t>-tyqe8rf{_4aiO%YGcdLGo8NN@dda zV-|CMw4#mdWX)VIL&APs!exf=b|mAQ>76YWmy1H_3Z+ECf}LlOb9%l+db3DU-bulv zh#3$JMepnD-TK7QHBvs_eL}F;sYbC_cPthYyEN72pQt$&{8+>d25mc@xy(IdsZ52h zQ7#78V!|Q4Zjphnte2u%=S1iKm8MvXM-@tiAr!U2>+Xg-siEQMVq$8lrfw*@u)}$6 zU!mwucBXf*Gr7b0M9uS#S}EAF+88e?`F3Fwd75OZPu3`zMI*b_cN)KPg#a4k1+>v^ zYM~3qw6K^Q;@n_ju4rwiU4$qjDj#_V_DTri5Url-A%hnkI7~c=y1bC+DuUhCl#g=S ztz}bbNi$PvS<9u;9@U*MJ<526+(jDJ8&% z)GiCkknc6Ts|Ypu0_qxktMGk*Km887K6iOM7Ixe4Iw!v0f@VYOooK{Dz=rN|q9Msb z&<2N`aD!~2!3H-v;YMyDY=fJea9FXh*9Px%!cD4${Wh38VbKLwwF?F86RklH^`j4* zUQh*t)RR%D7>5s&)Q@TGrYE2dcTtar2;eb-c!Cg~p%E_;#ux0xce3+?TKx;n%!O9w zr6;6~o|Y)uSsWeg91gQvh|&)l4DTN@rgC(09AS(}E;mOP$5Egq5@{A6g>h_ag8HkY k0@Md0YiM2tm!3m%zkzofgc5PcgvUdM5pZJL%8D4zwAwh)AJYlT1oE=}nnxRTqG6K^UP*8zX@&fmx% z;0#DD0t9#d6Np)dHhf%WcW36kdGq%B&re?gv~kyhg(V9Yaj66omrX3I#}$sN77Q$L zT(fW;H#lxG%&&M!BI7g|Mah#O@%o|k8Q30!u^B```jA0uGL3FU8fHS?+8@$~1UgiB9D;&2N%*{dgo8Rh< zvUnh$1&XaULGF5CCU=JSAKX)%HfAtOFdMgV$3_`8L&*<@!(pG=Y&6hhs86RqK3nN& z9FJlW{SPU}s*N?QGl(f@r++91DMMku^H+X?W#GpXP5G*w=Ksr*W%70Ag$ct#u;fJAD~S+&$duJMHK8uYS#<-$oemIOqV+V literal 0 HcmV?d00001 diff --git a/regression/strings/StringValueOf02/StringValueOf02.java b/regression/strings/StringValueOf02/StringValueOf02.java new file mode 100644 index 00000000000..a730af26c02 --- /dev/null +++ b/regression/strings/StringValueOf02/StringValueOf02.java @@ -0,0 +1,9 @@ +public class StringValueOf02 +{ + public static void main(String[] args) + { + char[] charArray = {'d', 'i', 'f', 'f', 'b', 'l', 'u', 'e'}; + String tmp=String.valueOf(charArray); + assert tmp.equals("difffblue"); + } +} diff --git a/regression/strings/StringValueOf02/test.desc b/regression/strings/StringValueOf02/test.desc new file mode 100644 index 00000000000..00835385bc8 --- /dev/null +++ b/regression/strings/StringValueOf02/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringValueOf02.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringValueOf03/StringValueOf03.class b/regression/strings/StringValueOf03/StringValueOf03.class new file mode 100644 index 0000000000000000000000000000000000000000..886aedc6b1d40d822d3bebede947ebfa4dabde7d GIT binary patch literal 748 zcmZWm%Wl&^6g?9=9>;N;X_}T4D9-{(TL=;rn^p)EK&q6qi{MIbR(3L}TwDkI=nwE0 z`2p5|)FMEz=bu2_Nod1kb7$s0&N=tY_n)7>0@%P^3l^3vT*RdUOk6gxtR7c5u39j# z#Bt5Sb==^%$uPg-C5epFU>GG&gT(Vg*=Jz;48~Rv1?eLOtybS-(3``)WGJ$VQPW3Lf<(Ltk=#zAzjsRm~{sn>hi_Fj$qIaWAsF_>Gu@Hf8I z8D?=$J`WUHWiq+vg_+zP+<$OSVcM9%ERET?jXO4qu!(ly`=N~*>I~H>@sqP{p2hJn zCcXdQaje={!#abQ4(p`|HdGbGo^v%XA%SoY6FlT~R(1+sjfzR0AH1emC*mFcE|?8Gd^61|q`WOU|N zPr=@)MhJ?=ILT1J9LjW8t#6>yFt8)cFL_rJeaF>B;JA4)a9l$LE_}x|Md-M~5E(@- zq|;h6jE~5*-$NUrvR>9tkRPG=8HRfb{!MY_#++rsCn0DM`$KTFN%}lxieNv`=BRKi pP-^j9`^H!#FjqEDP#A&hZ=q`+piME)_E0!^M!zEmC*nI literal 0 HcmV?d00001 diff --git a/regression/strings/StringValueOf03/StringValueOf03.java b/regression/strings/StringValueOf03/StringValueOf03.java new file mode 100644 index 00000000000..0c51518b300 --- /dev/null +++ b/regression/strings/StringValueOf03/StringValueOf03.java @@ -0,0 +1,9 @@ +public class StringValueOf03 +{ + public static void main(String[] args) + { + char[] charArray = {'d', 'i', 'f', 'f', 'b', 'l', 'u', 'e'}; + String tmp=String.valueOf(charArray, 3, 3); + assert tmp.equals("fbbl"); + } +} diff --git a/regression/strings/StringValueOf03/test.desc b/regression/strings/StringValueOf03/test.desc new file mode 100644 index 00000000000..19921a8e98f --- /dev/null +++ b/regression/strings/StringValueOf03/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringValueOf03.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringValueOf04/StringValueOf04.class b/regression/strings/StringValueOf04/StringValueOf04.class new file mode 100644 index 0000000000000000000000000000000000000000..5a0d670146c1cc44317c411ef7e8ef77c246899c GIT binary patch literal 688 zcmZWmT~8B16g{`Q-D#JFmQt{a6j6j0jrha^bh!~ zCSWwtcmI>dJ6oZCWRjWtdG5JqzW@CE6+jF3eE6vOxQ-h|6tGypP3tTP)O~oU2`u}# zg%yF@gt=82$I2vn7{yO@EPJ6E5U5M=+B(w7BZAXt9uVB^;Xn~eJ33M?(&L^o`?i=9 z$5Kaxg~schBY7q_Lm3@zb`qnb!!6r5-AQEs?XEn@>ILo)3hjRQ8{F>+x&k$7D=6^GK_7(AL%jVR+CjMO$Kd;EHw)?P_Z^@ za7C8&Nm5R*&RwkVkNNzKRIb@o*>b=dVutS$drSNhzxj;|(0f~mGT&YnBor}=3fs2y zC34&hEIaMRPsr_lfHOk%e#JdUeuSwn@LpX&e6t|A45R{=?L2!P1fM!{nd3+i^aFJg psB&Qbib^Y+3Cvas=O~UK+;?!Dk8mc4m$WPj;|7l{`GsuYwO{$qh?F%VLI@Z{1QawuOFY1dlm!*^1ab&P6?mE?BQ>yWU_baV`2(KS zDzLN)?))bxdp1H)FZ0pe@Ad09bA9{s62LNExo}Z&F^R`{=P6LXmscpfOjJK@9?CPhs$Bm0xt=bLCf{KIo^k1H)N&%kO@>h)UZe> z4nW(jL)DJ|3iV+Gan_eX7_T;J|Ifw_snbOIktukP?o+PT*uuh~QNw4S*`wPa=ms++ qQ0Bn+y_V&)DKJ{fog?3au)n~zzQY7y# literal 0 HcmV?d00001 diff --git a/regression/strings/StringValueOf05/StringValueOf05.java b/regression/strings/StringValueOf05/StringValueOf05.java new file mode 100644 index 00000000000..03854f575b0 --- /dev/null +++ b/regression/strings/StringValueOf05/StringValueOf05.java @@ -0,0 +1,9 @@ +public class StringValueOf05 +{ + public static void main(String[] args) + { + char characterValue = 'T'; + String tmp=String.valueOf(characterValue); + assert tmp.equals("A"); + } +} diff --git a/regression/strings/StringValueOf05/test.desc b/regression/strings/StringValueOf05/test.desc new file mode 100644 index 00000000000..ccb5b3dc440 --- /dev/null +++ b/regression/strings/StringValueOf05/test.desc @@ -0,0 +1,8 @@ +KNOWNBUG +StringValueOf05.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringValueOf06/StringValueOf06.class b/regression/strings/StringValueOf06/StringValueOf06.class new file mode 100644 index 0000000000000000000000000000000000000000..e9a8065210a235df735a15b77a18eaf94156a2fd GIT binary patch literal 687 zcmZWnT~8B16g_u$yVEWUEu~-;5m3+;3HU(dfre;M5)+Vz8WP}X+74uJ+3J4qWBLbp zMiVfa=)3<(!=0^Am6!Rr_nvdlJu^RlfBg<%1y4PAsCu}Idj;e%na6!|nG$&5!9`VI z+QSTH1s)Q{=42eJDAC<8ex+mC3RH(c`vkY4L!GP>>{@-7;B0g|ics9rp?aI1v{dxY z6m#N4>X0x|JJ>pwr*b)v;n8w4iFA0hW`M)ZM7G~=%MV$-z#~Gw(GLEQd(CbdwbiCJ zRFyt#R|cutIehkf$q@P&#t6fF%wgWg5PX8Qy6WRGo)D^oo-eNlc^yUFh^79=CQ$QH z#{!`=0PVDnRXh17)Q1toXSjSg0i!7M z*_1Y6F&LOBiN@p?Slgdq_fT0ZI~U0HF!T-X-X+8j!(wGDWjK7!G0J5b{7ZNp<46JY t3)3V};lTKfmX)k2Fj~%EpwNSG&fwUeVGkIubs3f%EdPa3Kan-Oa|N)_hcf^G literal 0 HcmV?d00001 diff --git a/regression/strings/StringValueOf06/StringValueOf06.java b/regression/strings/StringValueOf06/StringValueOf06.java new file mode 100644 index 00000000000..b13a3899f0f --- /dev/null +++ b/regression/strings/StringValueOf06/StringValueOf06.java @@ -0,0 +1,9 @@ +public class StringValueOf06 +{ + public static void main(String[] args) + { + int integerValue = 7; + String tmp=String.valueOf(integerValue); + assert tmp.equals("77"); + } +} diff --git a/regression/strings/StringValueOf06/test.desc b/regression/strings/StringValueOf06/test.desc new file mode 100644 index 00000000000..c78afa98f2f --- /dev/null +++ b/regression/strings/StringValueOf06/test.desc @@ -0,0 +1,8 @@ +KNOWNBUG +StringValueOf06.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringValueOf07/StringValueOf07.class b/regression/strings/StringValueOf07/StringValueOf07.class new file mode 100644 index 0000000000000000000000000000000000000000..36e9401884cee02e9c9682975e101417a17d58e4 GIT binary patch literal 916 zcmZWoZBr6a6n-u&yRfW+h(s?WmKInF7G?!CI#wSV(`ImNv`-6MnYCrt_Qje03V)!_ z*$g%{)%Si!f1{>z7ZJ(*aPQf3pYxn^pL6c7zh8d*Y8>#UNAwz&a8JQ~jRacOki-Oowp1Q|8XjPUAv=s+8%XfnacqY!`ClCh z9%^`m$0G^*m{HdU*W(>h%=SHoslFbDU3yJoc!cMAr^=ul_3uZB!pq`C(WogwX`_ME zkV8SU&rmB|3_34@Ns7MMflk>`1k(HntU?Mf%L!t{s`Uolf8L=VjpkTogK}cH_*SZ=c Gz4i~F)WtRc literal 0 HcmV?d00001 diff --git a/regression/strings/StringValueOf07/StringValueOf07.java b/regression/strings/StringValueOf07/StringValueOf07.java new file mode 100644 index 00000000000..c4c44435d22 --- /dev/null +++ b/regression/strings/StringValueOf07/StringValueOf07.java @@ -0,0 +1,10 @@ +public class StringValueOf07 +{ + public static void main(String[] args) + { + long longValue = 10000000000L; + System.out.printf("long = %s\n", String.valueOf(longValue)); + String tmp=String.valueOf(longValue); + assert tmp.equals("100000000000"); + } +} diff --git a/regression/strings/StringValueOf07/test.desc b/regression/strings/StringValueOf07/test.desc new file mode 100644 index 00000000000..7b19c4ff67b --- /dev/null +++ b/regression/strings/StringValueOf07/test.desc @@ -0,0 +1,8 @@ +KNOWNBUG +StringValueOf07.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringValueOf08/StringValueOf08.class b/regression/strings/StringValueOf08/StringValueOf08.class new file mode 100644 index 0000000000000000000000000000000000000000..356ddbbb9d4b840183665cc3543a33134f8f4808 GIT binary patch literal 694 zcmZWnT~8BH5IwWq_I8)WmZe}pu@z8TBtQ%%CJ=)Gc>;N;ArYQ#+bg-aY;`~QG5rHP zqX`&I^xglYaqbqVA1`y~&dfP8bMF1|>&rI)t5|d~f+>5W4!D@c9S08X7BOQk_XKJ# z1f~S)F79JiV2&_8FXLE6iSC8*mX2jRP+bBY5DM!$)X8%~uF>2l*qgnsB9wM?s9vQf zZ56#X#hf^iIwVXs4tI{_say_Zc(mL~A{`#B8Q^Fuk)3zD@_kk>Fi$A1cY-T&x7ACd zj@s6SsxpA>%OF*IZ&#iz8A1=YP-2*e2YBeg!zlNBvh;Mt!y_~Z)nV5c*Q>mYqF%(q z{=+BG^ss=(gz^xy*FILANIyZ$FV_V3A z#9$xe?3>aSECvI0-`bk{jNI-=*nLzM{rm+AeT;mCcyo#3cf(?3EIw@Z^NcE>$X}(# yw!#qy^b<8pV1fgaH?yo}O@T4rxq#b;u+L!UKEWO`Ue9G%^02%OGyUzXVf8mK-iSK@ literal 0 HcmV?d00001 diff --git a/regression/strings/StringValueOf08/StringValueOf08.java b/regression/strings/StringValueOf08/StringValueOf08.java new file mode 100644 index 00000000000..539c60e5a9f --- /dev/null +++ b/regression/strings/StringValueOf08/StringValueOf08.java @@ -0,0 +1,9 @@ +public class StringValueOf08 +{ + public static void main(String[] args) + { + float floatValue = 2.5f; + String tmp=String.valueOf(floatValue); + assert tmp.equals("2.50"); + } +} diff --git a/regression/strings/StringValueOf08/test.desc b/regression/strings/StringValueOf08/test.desc new file mode 100644 index 00000000000..a7d90b1b9ef --- /dev/null +++ b/regression/strings/StringValueOf08/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringValueOf08.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/strings/StringValueOf09/StringValueOf09.class b/regression/strings/StringValueOf09/StringValueOf09.class new file mode 100644 index 0000000000000000000000000000000000000000..e852bce13a4efeac1af59da4f7f6ac6010aa2498 GIT binary patch literal 702 zcmZWnT~8B16g{`y-D#J_mQt{yC{>ge1x(6|ftVW5_<-YC}JM;bL=TiWySaRWE#%VU+zCP`L`{?2_uH@lj zHixU`a!p{)MGi9pRTtNBLtvgTIWMC~g|Y4h(WZ`M+gDuz?Gv1J9q9NzAzQ2O5v+|~ zR}l(ZI#AomQCo$(CYb|AQU`?T+Ow@g*_SK63=URWaj1iXH3J-P#j^9_iF}#n3*02+ z);s=ha<|n>!j5{R4OMvv+mn8xcAnq8w`>SK6i{TChg(?iFpdiZ(P%6;czLLyPN<9u zKRD~=VHoy8*82~oz@mrSxI-w8Ks)V2)rtRd4PjiVKNLfls%_T)?~v!DUM13xOu`@G zA>~?~2U!>u+VFYWJgcsXbf~)LVtGVy!T}!jKC1j^9zQ7+E2djMWx*^cvYp`DEbqj- zy?6q8XA)6j>!eOX9+N2Z*`)3w1B>@+8JWimpI~jjhdn@fspK3(3^4Wuxu++{e>F6j zl%|vdY_<+l@t@%@GsV$7=m+Mq0@LiccrIo&tqM$(++&OlAgnjAvL9fN7|(t3&iEl0tMVnGpGK+uFYh|!=t6?mwU08iU?C5OjV@AmjH{R2L$ z2^dZE-T$O<_6ih@FSE0=^L_Kp%>MlS^*ewythgv)+QDrXcQ8{#5qBNb&1F_#&V|6V zz&#iDF)#3dFflKaM8!JjN6CvIk)2TW2y{RwYy?rDpAzzo<{rV??DrI*+zKMKlb&=` z{K_Qr!-)(c!c^n1bu3TiYABSY}F zW7ho-ufURrWjrEOMxfo!vFhr-LPHoqoDLNc78=+393s}6*FqPq^8nTRRE7y*@_z`P zaCuaDGvqb!5PK>KV%57+&$H7hKkyC?Fvr_0@s_DlGtIM?2bs~Zt?+GzPvX;FJO_O= zi5O>F$b!UR9~11G)Yr%{7?|~Qt)(x>Z-0U{Ky}%-&rlek^bKPF9L^8JlFL|pSnS)3 zD!}1yRA*b|ND1@{b%9BNDGuGdQnQwo1;+j28QcMc^#NA?GprHkr82`~Bj-Ic`fFLq GTYmttSCRDq literal 0 HcmV?d00001 diff --git a/regression/strings/StringValueOf10/StringValueOf10.java b/regression/strings/StringValueOf10/StringValueOf10.java new file mode 100644 index 00000000000..044586124a7 --- /dev/null +++ b/regression/strings/StringValueOf10/StringValueOf10.java @@ -0,0 +1,9 @@ +public class StringValueOf10 +{ + public static void main(String[] args) + { + Object objectRef = "test"; // assign string to an Object reference + String tmp=String.valueOf(objectRef); + assert tmp.equals("tesst"); + } +} diff --git a/regression/strings/StringValueOf10/test.desc b/regression/strings/StringValueOf10/test.desc new file mode 100644 index 00000000000..5de3d5aade7 --- /dev/null +++ b/regression/strings/StringValueOf10/test.desc @@ -0,0 +1,8 @@ +FUTURE +StringValueOf10.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring From 47dbc2ed91d6391b7c2dd20994e3eb9d0f7d33c9 Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Wed, 22 Feb 2017 14:26:42 +0000 Subject: [PATCH 016/699] =?UTF-8?q?=C2=A0added=20test=20cases=20related=20?= =?UTF-8?q?to=20string=20class=20substring=20methods?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucas Cordeiro --- regression/strings/SubString01/SubString01.class | Bin 0 -> 829 bytes regression/strings/SubString01/SubString01.java | 13 +++++++++++++ regression/strings/SubString01/test.desc | 8 ++++++++ regression/strings/SubString02/SubString02.class | Bin 0 -> 744 bytes regression/strings/SubString02/SubString02.java | 9 +++++++++ regression/strings/SubString02/test.desc | 8 ++++++++ regression/strings/SubString03/SubString03.class | Bin 0 -> 734 bytes regression/strings/SubString03/SubString03.java | 9 +++++++++ regression/strings/SubString03/test.desc | 8 ++++++++ 9 files changed, 55 insertions(+) create mode 100644 regression/strings/SubString01/SubString01.class create mode 100644 regression/strings/SubString01/SubString01.java create mode 100644 regression/strings/SubString01/test.desc create mode 100644 regression/strings/SubString02/SubString02.class create mode 100644 regression/strings/SubString02/SubString02.java create mode 100644 regression/strings/SubString02/test.desc create mode 100644 regression/strings/SubString03/SubString03.class create mode 100644 regression/strings/SubString03/SubString03.java create mode 100644 regression/strings/SubString03/test.desc diff --git a/regression/strings/SubString01/SubString01.class b/regression/strings/SubString01/SubString01.class new file mode 100644 index 0000000000000000000000000000000000000000..861bf6905d377ed4734838615a71b208ff4870df GIT binary patch literal 829 zcmZuvT~8B16g|_g-EOybTS~1UA`044q+oc17!frgDf&=D0zS=dhh}iQtNY=zzoUP^ zXEiB_Ci?Dw(s*YpZ4D-yosVQkHhm$g3&0zXjEn^cfW!cdqoqoHkL3)^II8vN2e7Y-3; zuEypW@?mU;NedX}8;8xSouU4UcQJQEMVNudqPtBRK&^53|H#tR!+}fVBWh2CG7!B< zJ=F6kCV*yliWPbdMS3O7s;kz}E)BAcGW{!bTB4QFnq9vD`=p4Nqkk^Bq+(FTJna?r z1BIq(eNstvT2^(0^wDQzhNx~-vLob%D13u>4zP0`_5|Mu>^jFZGJA)3;1`ePVnkaR`(vg%Qjlw9H3j(qE97ieDC?gtADP Mk5#ERlH3b_0AX3L1ONa4 literal 0 HcmV?d00001 diff --git a/regression/strings/SubString01/SubString01.java b/regression/strings/SubString01/SubString01.java new file mode 100644 index 00000000000..c99db9b7308 --- /dev/null +++ b/regression/strings/SubString01/SubString01.java @@ -0,0 +1,13 @@ +public class SubString01 +{ + public static void main(String[] args) + { + String letters = "automatictestcasegenerationatdiffblue"; + + String tmp=letters.substring(20); + assert tmp.equals("erationatdiffblue"); + + tmp=letters.substring(9, 13); + assert tmp.equals("test"); + } +} diff --git a/regression/strings/SubString01/test.desc b/regression/strings/SubString01/test.desc new file mode 100644 index 00000000000..8eea70cf458 --- /dev/null +++ b/regression/strings/SubString01/test.desc @@ -0,0 +1,8 @@ +KNOWNBUG +SubString01.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/strings/SubString02/SubString02.class b/regression/strings/SubString02/SubString02.class new file mode 100644 index 0000000000000000000000000000000000000000..d758b7baf0b6929136ac7bc16c5f232333cb203d GIT binary patch literal 744 zcmZWn!EVz)5Ph3Cv17X=b<>gp1yWi_+CmZPtrY?lkdV@H2m-Y|t?g~J#j(L&^D+4W z&VZCkAit?(=psgg;YJ(C&tBM~yNLx$>(jHPZKJ8H@dV z=!^8V22)_jWz4Y9IqIG8k9;%Y@nEyBQW+1nb>d84@!;Jae_!BDtTI?TLG+K@?k9N~ zh!;{*HTt!;=^6+9jcvMZEVh5otPu+Sur1NIwj6Z7 zU}4e1vV#?@T4*!Owt1F`RLLaHp2>{+kq8;s2}5O1#!@|IFgo4W4Ca0k3Wi2c#^NX+ z`XYU$lPNIdGG0s4}3e~@nE~JQW+0+bz!})c<}a+zbo=BtTEVoLG%~g=_h#_ zh!;{rdHvj$vB_ zMV+Cn1SPxZpv%yjQhRza@AEWGQij@5|EJMea@qdVZL)EJVD*NM%!jy zOOHyH0j8Cr)1%iC-Hh(?#yQw0oroDaD}|FtqlsCvb?Pyd8g#dtrQW7j_3C37ho51N zFt^n#k5L(+_6^qYIqV-AsZ<~}VUk^@$_f#%unHS< Date: Wed, 22 Feb 2017 14:27:30 +0000 Subject: [PATCH 017/699] =?UTF-8?q?=C2=A0added=20test=20cases=20related=20?= =?UTF-8?q?to=20StringTokenizer=20object=20used=20to=20tokenize=20strings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucas Cordeiro --- .../strings/TokenTest01/TokenTest01.class | Bin 0 -> 1409 bytes .../strings/TokenTest01/TokenTest01.java | 24 ++++++++++++++++++ regression/strings/TokenTest01/test.desc | 8 ++++++ .../strings/TokenTest02/TokenTest02.class | Bin 0 -> 870 bytes .../strings/TokenTest02/TokenTest02.java | 17 +++++++++++++ regression/strings/TokenTest02/test.desc | 8 ++++++ 6 files changed, 57 insertions(+) create mode 100644 regression/strings/TokenTest01/TokenTest01.class create mode 100644 regression/strings/TokenTest01/TokenTest01.java create mode 100644 regression/strings/TokenTest01/test.desc create mode 100644 regression/strings/TokenTest02/TokenTest02.class create mode 100644 regression/strings/TokenTest02/TokenTest02.java create mode 100644 regression/strings/TokenTest02/test.desc diff --git a/regression/strings/TokenTest01/TokenTest01.class b/regression/strings/TokenTest01/TokenTest01.class new file mode 100644 index 0000000000000000000000000000000000000000..70e112fbafba43a04d1e0f208ed307c70c3dedac GIT binary patch literal 1409 zcmZuxOLNm!6#i}`>&l8kVh2M^5)cI%2Ld4v0@!H^gaDy=bjBGvz)G<%K_E*(l9^%8 z8ur=1uwm0p>5O4uNY^l|;P23;=gRRTj5qi7o%5Z?ccjn%z262fja362$8;Rmal*jQ z7)c_BQ5`2aP8k@(X#;04orH9M*W^B(<;Fx95XG`ubzftt7K}lS5BwOE_|4?{q zB8<*XoRNGc4q|}euw9M(iXAy6D>Fh}y(2nB(}>#3fv27^x>} z`S&d0ii+@}FmIhG8*BH470EcEWd|Z}P}o-LtLqO$DdMIoG zU2gPkAqf1y#0@MmB%5iPxQXAWJ2G3^WWEeWd&b>urE)BpSjNhpOzKS}jXHFeArWr6 z4pEQfI`qAxM_ZA_Ct)Niq^(~iicFos@yCBB*&>Q7>`H+l)v9*Ui^PTq82Dq`t%}uq zQt`#nw$Qs4gQN6Cary#T-+&wgIw@dsE@{ouZJ2gO zd*b9r%r zEKl#Np?3@G4fkR7;Ybw~#`BG@es`|HOWLqV9en>??T;6GH*~ zUrccv<~Xtg6P)(?jnRow%fDlS9)^a7b|{qEg2`Ej)f8wtRsu++`)k<01+Kn^s{9S3 Vm2*QZ88?A0^OBVGC|$bn)Bmw>Ko|f3 literal 0 HcmV?d00001 diff --git a/regression/strings/TokenTest01/TokenTest01.java b/regression/strings/TokenTest01/TokenTest01.java new file mode 100644 index 00000000000..2180bc94c1d --- /dev/null +++ b/regression/strings/TokenTest01/TokenTest01.java @@ -0,0 +1,24 @@ +import java.util.StringTokenizer; + +public class TokenTest01 +{ + public static void main(String[] args) + { + String sentence = "automatic test case generation"; + String[] tokens = sentence.split(" "); + System.out.printf("Number of elements: %d\nThe tokens are:\n", + tokens.length); + assert tokens.length==4; + + int i=0; + for (String token : tokens) + { + System.out.println(token); + if (i==0) assert token.equals("automatic"); + else if (i==1) assert token.equals("test"); + else if (i==2) assert token.equals("case"); + else if (i==3) assert token.equals("generation"); + ++i; + } + } +} diff --git a/regression/strings/TokenTest01/test.desc b/regression/strings/TokenTest01/test.desc new file mode 100644 index 00000000000..02a11e8e392 --- /dev/null +++ b/regression/strings/TokenTest01/test.desc @@ -0,0 +1,8 @@ +FUTURE +TokenTest01.class +--string-refine --unwind 30 +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/strings/TokenTest02/TokenTest02.class b/regression/strings/TokenTest02/TokenTest02.class new file mode 100644 index 0000000000000000000000000000000000000000..09f38782aa153f91c4836a3c3b5a75cd604e2f76 GIT binary patch literal 870 zcmZuvO-~b16g{u=@ut&3O0m#d!Gb8IAgzS3076uRjYSu2OvKf6`qB)vGdMH#7w{{( zGHzI_5fV*s@5Vo5toId5G3jF7y!Y<8=bm%#`}ybFC4hB2Hen%W;I4rg6SKG%hl#v_ zIeD1pxNpKhj$^^Z13ctdWSCsA!%zf~>wDpIH?-?5(O_VQ4Ena~xzP@TQdoM;pzit& z!7yHNJ@K;Bu8W{1!4zoQuE#J{cw0HL-`k~@?KMl)C~&>zmP{P0Mz(W&V4w8y90iUg z24mZ4{o^;QekX9mzAM?1HUC(6H4#STwN=SyVH`<@S-TVYZ98(Ed_=*#V}~N&6rKp^ z&Zqh;PrMe2Shg^RTMP+`4#E~z@Q5KZ6!>)DdM^n4fY3MUa;#b?p-gIq39sr$!ilJ1 zBW(T$yt2-qg(oeS5*7<1`ZAJ47wWVCo$BnY_e)lc^()TzxjD%*NU{{2pcguZXC!)$_Af|sn$RUEJxqghOmR%p z%H&5DexpbiJxW)HF-kCyxpuqWw*^e3%yT5V;OZGv Date: Wed, 22 Feb 2017 14:28:21 +0000 Subject: [PATCH 018/699] =?UTF-8?q?=C2=A0added=20test=20cases=20related=20?= =?UTF-8?q?to=20validate=20data=20from=20user=20using=20the=20ValidateInpu?= =?UTF-8?q?t=20class?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucas Cordeiro --- .../strings/Validate01/Validate01.class | Bin 0 -> 1415 bytes regression/strings/Validate01/Validate01.java | 30 ++++++++++++++ .../strings/Validate01/ValidateInput01.class | Bin 0 -> 880 bytes .../strings/Validate01/ValidateInput01.java | 38 ++++++++++++++++++ regression/strings/Validate01/test.desc | 8 ++++ .../strings/Validate02/Validate02.class | Bin 0 -> 1187 bytes regression/strings/Validate02/Validate02.java | 22 ++++++++++ .../strings/Validate02/ValidateInput02.class | Bin 0 -> 880 bytes .../strings/Validate02/ValidateInput02.java | 38 ++++++++++++++++++ regression/strings/Validate02/test.desc | 8 ++++ 10 files changed, 144 insertions(+) create mode 100644 regression/strings/Validate01/Validate01.class create mode 100644 regression/strings/Validate01/Validate01.java create mode 100644 regression/strings/Validate01/ValidateInput01.class create mode 100644 regression/strings/Validate01/ValidateInput01.java create mode 100644 regression/strings/Validate01/test.desc create mode 100644 regression/strings/Validate02/Validate02.class create mode 100644 regression/strings/Validate02/Validate02.java create mode 100644 regression/strings/Validate02/ValidateInput02.class create mode 100644 regression/strings/Validate02/ValidateInput02.java create mode 100644 regression/strings/Validate02/test.desc diff --git a/regression/strings/Validate01/Validate01.class b/regression/strings/Validate01/Validate01.class new file mode 100644 index 0000000000000000000000000000000000000000..a5a99f5efc122f3706a204ede0e0d0bfb70352c9 GIT binary patch literal 1415 zcmZuxQBxaL6#gzGxtGmCl7&#x+IH2dDYOA>C?#NROiN1*2?}D8T4$DIEnAY^%U06~^Hkq^ce)rsSzw@1Q_wRpx{}VtSUn#hNX@MDm zYXa8=assmga{}`UKE#a?WRT}rP!PwoL~cs6ID%VP5-2EG#)?EflIFHF9}C=(@1npb z0ws>S3hrT*<37Xq6~psP*S8$oyK8yIPTOoTum(eH#j-8`Hp6iC>NZ29< zO0TnHx?9qj7CMGyGfZY5m7f~VjM=tfKbhV1UCVy5EH{pB`bKka-RK7X91l3w7{p4m zeH>rebb4;nT(xAh#J174T83}V&F5q|6_;?CIMix2vh{kML2EP``WiiYksf{F=B*`S zTm9}E$0h3Vqk*?;xfCu|t=(8GuF`ok`TU}MI3B9_6lE1};UdG-fO9bv;-2d|u8MW( zR6&`es$v755xF({nWU#1t(I$g9>?b@HnFAR3+cNp&6g-MBtysVt*+iA;Z)QlJ`v*G zUB@^*(o>E#%dfgT)n6%9P1@B`A-ou_8gr#haY{wc?! zio7B4nmlc8o*@b4(XQ8o>5F{ie%_pHbU1#2o;Y+IeqHB=bIg>oYNzc z>7$^QGrK|U;S(j(=qwZYAfMAP1Mf#gLi4H(?SJ95VZEIHdNMz*R@DRixwhUtPs_BA*P7}pXp=d z0I8Qy4)D_-h}U03{p(sEqapZh2wv}F>;Pjgk5z-kuJ&U&`=4CXbv*ds3wllXz+{D>+1OgnzTc^s0o&q>NF6g>;^F9i@B?{U2U z|35I1N~blA)7c-Klp!DJ4WzWpE1W+7j~pU0{2P=3`LHDNkSK=KJF;-uAh)ak0T3ZI AF#rGn literal 0 HcmV?d00001 diff --git a/regression/strings/Validate01/Validate01.java b/regression/strings/Validate01/Validate01.java new file mode 100644 index 00000000000..3443cd30588 --- /dev/null +++ b/regression/strings/Validate01/Validate01.java @@ -0,0 +1,30 @@ +public class Validate01 +{ + public static void main(String[] args) + { + String firstName = "XXX"; + String lastName = "YYY"; + String address = "ZZZ IIII AAAA 5689"; + String city = "Oxford"; + String state = "Oxfordshire"; + String zip = "OX37AF"; + String phone = "+4477777"; + + if (!ValidateInput01.validateFirstName(firstName)) + assert false; + else if (!ValidateInput01.validateLastName(lastName)) + assert false; + else if (!ValidateInput01.validateAddress(address)) + System.out.println("Invalid address"); + else if (!ValidateInput01.validateCity(city)) + assert false; + else if (!ValidateInput01.validateState(state)) + assert false; + else if (!ValidateInput01.validateZip(zip)) + System.out.println("Invalid zip code"); + else if (!ValidateInput01.validatePhone(phone)) + System.out.println("Invalid phone number"); + else + System.out.println("Valid input. Thank you."); + } +} diff --git a/regression/strings/Validate01/ValidateInput01.class b/regression/strings/Validate01/ValidateInput01.class new file mode 100644 index 0000000000000000000000000000000000000000..5efab9300fcd9f0ac4b50c6e91c370bb287cb27e GIT binary patch literal 880 zcma)(O;6iE5Qg6gBsRw2@DV6b2(%RPAs49Vp(?6`kSZZXfRu_uJ`S7M0;9x1_9hZ3 z{G(oa0f_@Ypg*eW7;vCyrPha?nRlMuoqhf5_w5~kZLAqEFsEbQzyeWx zGP%;3=!uP%@J}|%GVuJ9&-n@=9kV47qgE{KI!@q*A;FB5Jx^W`#^SOp`4YltTvxpF zXWgUIj?Z1A-022Qo+TP>`uK6QegC{GH@DtLLzx(bNf@v0+Ld}$*!?ILG_0CiP~EaW)w%d^Wj{+< z*ygVF;tA~Gle347Gq)-Kk{-+^Xl)^zr*4Q9jPTEnJ{@cxOkT&hTI5I^lZ6}5Pfpkp zUQ_oX@g@st&LcF7#J#E&CKJ~f`tbrzGCZMzhZV5F@T3Y(DqxG@DHWVjz!`?8{}-NT aIHQ6!#mQNQXH>ARfLGb7S#~IaSAPH|Ae`<1 literal 0 HcmV?d00001 diff --git a/regression/strings/Validate01/ValidateInput01.java b/regression/strings/Validate01/ValidateInput01.java new file mode 100644 index 00000000000..961b02f2d30 --- /dev/null +++ b/regression/strings/Validate01/ValidateInput01.java @@ -0,0 +1,38 @@ +public class ValidateInput01 +{ + public static boolean validateFirstName(String firstName) + { + return firstName.matches("[A-Z][a-zA-Z]*"); + } + + public static boolean validateLastName(String lastName) + { + return lastName.matches("[a-zA-z]+(['-][a-zA-Z]+)*"); + } + + public static boolean validateAddress(String address) + { + return address.matches( + "\\d+\\s+([a-zA-Z]+|[a-zA-Z]+\\s[a-zA-Z]+)"); + } + + public static boolean validateCity(String city) + { + return city.matches("([a-zA-Z]+|[a-zA-Z]+\\s[a-zA-Z]+)"); + } + + public static boolean validateState(String state) + { + return state.matches("([a-zA-Z]+|[a-zA-Z]+\\s[a-zA-Z]+)") ; + } + + public static boolean validateZip(String zip) + { + return zip.matches("\\d{5}"); + } + + public static boolean validatePhone(String phone) + { + return phone.matches("[1-9]\\d{2}-[1-9]\\d{2}-\\d{4}"); + } +} diff --git a/regression/strings/Validate01/test.desc b/regression/strings/Validate01/test.desc new file mode 100644 index 00000000000..e797b2735aa --- /dev/null +++ b/regression/strings/Validate01/test.desc @@ -0,0 +1,8 @@ +FUTURE +Validate01.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/strings/Validate02/Validate02.class b/regression/strings/Validate02/Validate02.class new file mode 100644 index 0000000000000000000000000000000000000000..1d9ddd04737b9414e691eb9c5a1576b5d60823e6 GIT binary patch literal 1187 zcmZuw*;3O`82(PTgf!4LEEW|B3djyZ*%2rOv8+O*%=+h>yYxa4pV2 zM`!fjSMXib{{%{5hLg-$zVk2NzntHHzyAb~Kt@6fxI`h%n5kO(AcRtj&8e#Wjf1-qwN;- zJOj%zgysy>aOWBPJ-s^&fs~ck86xY3sc)8xySly2h3TTG874zZ&&Tyc?N}QwXy*R# zmTMd4{w!Cl-*UCw(S}y?7C$0f2d-f%El z1-}?2HRt6k?!}`TW~uBBsp|HDW*(_0R(Xg)s)Z_GUB(7B$wZA?X7^Cfxm2Qi5_?DR zD%rPkm*(C^MhWrw6TxIYZ|jc3(A;xRm8jZsRWe1f-nD+>xO$P=z$z1&<|}o>8h%R^ zcFDD_6=#X0$NMhKAe6XJf!gC>T1L)_$Pw!zH9&0~Lf%(Qpn~slPzO8Ab*x zh+HF44|&oWs33L?DIOH&@{P3RTznpvc|>R*B;q0Z1mYy3p5_?B6p)N=It`)$QzW;5 zD0O2D@1Wolg|4F+?WEm~;6D-!2~Y)e-2Q=BOcBWB)0>+4J4~ez)lchoaeGW%NvRJV!|Pix-4)Uvyc^ z=F2DIOssc=-(IiC!1LRm3spiUX3HW*tytQ1oWKo3f*C7&p8QT2iOY)QO9;bpUG+|% zbPtYuK6i~uuOGB{mT0tzqleMH`lo&QVe@@7l!;-Ogx9rQyV|G;`#g$84a+80kReRp zYv+wpzP4r$h*F_QSgkvyddQ83ZKaDrRu2bhfiVAXBvp5Qe7q#g);8=<4K6k>?I$S< zTimr?Jb^uYboN{G#BIrE(!JRPtt({f*bT9OSNyZ1PY0U^lh+Zh<~S0^RPhS*ixakl z*Yur8yvag_^9ao$ai?m Date: Mon, 27 Feb 2017 00:18:27 +0000 Subject: [PATCH 019/699] cleanup aa-path-symex and aa-symex --- src/aa-path-symex/Makefile | 15 - src/aa-path-symex/build_goto_trace.cpp | 1 - src/aa-path-symex/build_goto_trace.h | 1 - src/aa-path-symex/path_symex.cpp | 1257 ------------------------ src/aa-path-symex/path_symex.h | 1 - src/aa-path-symex/path_symex_state.cpp | 799 --------------- src/aa-path-symex/path_symex_state.h | 350 ------- src/aa-symex/Makefile | 68 -- src/aa-symex/path_search.cpp | 517 ---------- src/aa-symex/path_search.h | 119 --- 10 files changed, 3128 deletions(-) delete mode 100644 src/aa-path-symex/Makefile delete mode 120000 src/aa-path-symex/build_goto_trace.cpp delete mode 120000 src/aa-path-symex/build_goto_trace.h delete mode 100644 src/aa-path-symex/path_symex.cpp delete mode 120000 src/aa-path-symex/path_symex.h delete mode 100644 src/aa-path-symex/path_symex_state.cpp delete mode 100644 src/aa-path-symex/path_symex_state.h delete mode 100644 src/aa-symex/Makefile delete mode 100644 src/aa-symex/path_search.cpp delete mode 100644 src/aa-symex/path_search.h diff --git a/src/aa-path-symex/Makefile b/src/aa-path-symex/Makefile deleted file mode 100644 index 9d3c4d96074..00000000000 --- a/src/aa-path-symex/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -SRC = path_symex_state.cpp path_symex.cpp build_goto_trace.cpp - -INCLUDES= -I .. - -include ../config.inc -include ../common - -CLEANFILES = aa-path-symex$(LIBEXT) - -all: aa-path-symex$(LIBEXT) - -############################################################################### - -aa-path-symex$(LIBEXT): $(OBJ) - $(LINKLIB) diff --git a/src/aa-path-symex/build_goto_trace.cpp b/src/aa-path-symex/build_goto_trace.cpp deleted file mode 120000 index a8d26f1b4bd..00000000000 --- a/src/aa-path-symex/build_goto_trace.cpp +++ /dev/null @@ -1 +0,0 @@ -../path-symex/build_goto_trace.cpp \ No newline at end of file diff --git a/src/aa-path-symex/build_goto_trace.h b/src/aa-path-symex/build_goto_trace.h deleted file mode 120000 index 3183a6b0910..00000000000 --- a/src/aa-path-symex/build_goto_trace.h +++ /dev/null @@ -1 +0,0 @@ -../path-symex/build_goto_trace.h \ No newline at end of file diff --git a/src/aa-path-symex/path_symex.cpp b/src/aa-path-symex/path_symex.cpp deleted file mode 100644 index f503f25c6e1..00000000000 --- a/src/aa-path-symex/path_symex.cpp +++ /dev/null @@ -1,1257 +0,0 @@ -/*******************************************************************\ - -Module: Concrete Symbolic Transformer - -Author: Daniel Kroening, kroening@kroening.com - Alex Horn, alex.horn@cs.ox.ac.uk - -\*******************************************************************/ - -#include -#include -#include -#include -#include - -#include - -#include - -#include "path_symex.h" - -// #define DEBUG - -#ifdef DEBUG -#include -#endif - -class path_symext -{ -public: - inline path_symext() - { - } - - void operator()( - path_symex_statet &state, - std::list &furter_states); - - void operator()(path_symex_statet &state); - - void do_goto( - path_symex_statet &state, - bool taken); - - void do_assert_fail(path_symex_statet &state) - { - const goto_programt::instructiont &instruction= - *state.get_instruction(); - - state.record_step(); - state.next_pc(); - exprt guard=state.read(not_exprt(instruction.guard)); - state.history->guard=guard; - } - -protected: - void do_goto( - path_symex_statet &state, - std::list &further_states); - - void function_call( - path_symex_statet &state, - const code_function_callt &call, - std::list &further_states) - { - exprt f=state.read(call.function()); - function_call_rec(state, call, f, further_states); - } - - void function_call_rec( - path_symex_statet &state, - const code_function_callt &function_call, - const exprt &function, - std::list &further_states); - - void return_from_function( - path_symex_statet &state, - const exprt &return_value); - - void symex_malloc( - path_symex_statet &state, - const exprt &lhs, - const side_effect_exprt &code); - - void assign( - path_symex_statet &state, - const exprt &lhs, - const exprt &rhs); - - inline void assign( - path_symex_statet &state, - const code_assignt &assignment) - { - assign(state, assignment.lhs(), assignment.rhs()); - } - - void assign_rec( - path_symex_statet &state, - exprt::operandst &guard, // instantiated - const exprt &ssa_lhs, // instantiated, recursion here - const exprt &ssa_rhs); // instantiated - - static bool propagate(const exprt &src); -}; - -/*******************************************************************\ - -Function: path_symext::propagate - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -bool path_symext::propagate(const exprt &src) -{ - // propagate things that are 'simple enough' - if(src.is_constant()) - return true; - else if(src.id()==ID_member) - return propagate(to_member_expr(src).struct_op()); - else if(src.id()==ID_index) - return false; - else if(src.id()==ID_typecast) - return propagate(to_typecast_expr(src).op()); - else if(src.id()==ID_symbol) - return true; - else if(src.id()==ID_address_of) - return true; - else if(src.id()==ID_plus) - { - forall_operands(it, src) - if(!propagate(*it)) - return false; - return true; - } - else if(src.id()==ID_array) - { - forall_operands(it, src) - if(!propagate(*it)) - return false; - return true; - } - else if(src.id()==ID_vector) - { - forall_operands(it, src) - if(!propagate(*it)) - return false; - return true; - } - else if(src.id()==ID_if) - { - const if_exprt &if_expr=to_if_expr(src); - if(!propagate(if_expr.true_case()) || - !propagate(if_expr.false_case())) - return false; - - return true; - } - else if(src.id()==ID_array_of) - { - return propagate(to_array_of_expr(src).what()); - } - else if(src.id()==ID_union) - { - return propagate(to_union_expr(src).op()); - } - else - { - return false; - } -} - -/*******************************************************************\ - -Function: path_symext::assign - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void path_symext::assign( - path_symex_statet &state, - const exprt &lhs, - const exprt &rhs) -{ - if(rhs.id()==ID_side_effect) // catch side effects on rhs - { - const side_effect_exprt &side_effect_expr=to_side_effect_expr(rhs); - const irep_idt &statement=side_effect_expr.get_statement(); - - if(statement==ID_malloc) - { - symex_malloc(state, lhs, side_effect_expr); - return; - } - else if(statement==ID_nondet) - { - // done in statet:instantiate_rec - } - else - throw "unexpected side-effect on rhs: "+id2string(statement); - } - - // read the address of the lhs, with propagation - exprt lhs_address=state.read(address_of_exprt(lhs)); - - // now SSA the lhs, no propagation - exprt ssa_lhs= - state.read_no_propagate(dereference_exprt(lhs_address)); - - // read the rhs - exprt ssa_rhs=state.read(rhs); - - // start recursion on lhs - exprt::operandst _guard; // start with empty guard - assign_rec(state, _guard, ssa_lhs, ssa_rhs); -} - -/*******************************************************************\ - -Function: path_symext::symex_malloc - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -inline static typet c_sizeof_type_rec(const exprt &expr) -{ - const irept &sizeof_type=expr.find(ID_C_c_sizeof_type); - - if(!sizeof_type.is_nil()) - { - return static_cast(sizeof_type); - } - else if(expr.id()==ID_mult) - { - forall_operands(it, expr) - { - typet t=c_sizeof_type_rec(*it); - if(t.is_not_nil()) - return t; - } - } - - return nil_typet(); -} - -void path_symext::symex_malloc( - path_symex_statet &state, - const exprt &lhs, - const side_effect_exprt &code) -{ - if(code.operands().size()!=1) - throw "malloc expected to have one operand"; - - // increment dynamic object counter - unsigned dynamic_count=++state.var_map.dynamic_count; - - exprt size=code.op0(); - typet object_type=nil_typet(); - - { - exprt tmp_size=state.read(size); // to allow constant propagation - - // special treatment for sizeof(T)*x - if(tmp_size.id()==ID_mult && - tmp_size.operands().size()==2 && - tmp_size.op0().find(ID_C_c_sizeof_type).is_not_nil()) - { - object_type=array_typet( - c_sizeof_type_rec(tmp_size.op0()), - tmp_size.op1()); - } - else - { - typet tmp_type=c_sizeof_type_rec(tmp_size); - - if(tmp_type.is_not_nil()) - { - // Did the size get multiplied? - mp_integer elem_size=pointer_offset_size(tmp_type, state.var_map.ns); - mp_integer alloc_size; - if(elem_size<0 || to_integer(tmp_size, alloc_size)) - { - } - else - { - if(alloc_size==elem_size) - object_type=tmp_type; - else - { - mp_integer elements=alloc_size/elem_size; - - if(elements*elem_size==alloc_size) - object_type= - array_typet(tmp_type, from_integer(elements, tmp_size.type())); - } - } - } - } - - if(object_type.is_nil()) - object_type=array_typet(unsigned_char_type(), tmp_size); - - // we introduce a fresh symbol for the size - // to prevent any issues of the size getting ever changed - - if(object_type.id()==ID_array && - !to_array_type(object_type).size().is_constant()) - { - exprt &size=to_array_type(object_type).size(); - - symbolt size_symbol; - - size_symbol.base_name="dynamic_object_size"+std::to_string(dynamic_count); - size_symbol.name="symex::"+id2string(size_symbol.base_name); - size_symbol.is_lvalue=true; - size_symbol.type=tmp_size.type(); - size_symbol.mode=ID_C; - - assign(state, - size_symbol.symbol_expr(), - size); - - size=size_symbol.symbol_expr(); - } - } - - // value - symbolt value_symbol; - - value_symbol.base_name= - "dynamic_object"+std::to_string(state.var_map.dynamic_count); - value_symbol.name="symex_dynamic::"+id2string(value_symbol.base_name); - value_symbol.is_lvalue=true; - value_symbol.type=object_type; - value_symbol.type.set("#dynamic", true); - value_symbol.mode=ID_C; - - address_of_exprt rhs; - - if(object_type.id()==ID_array) - { - rhs.type()=pointer_typet(value_symbol.type.subtype()); - index_exprt index_expr(value_symbol.type.subtype()); - index_expr.array()=value_symbol.symbol_expr(); - index_expr.index()=from_integer(0, index_type()); - rhs.op0()=index_expr; - } - else - { - rhs.op0()=value_symbol.symbol_expr(); - rhs.type()=pointer_typet(value_symbol.type); - } - - if(rhs.type()!=lhs.type()) - rhs.make_typecast(lhs.type()); - - assign(state, lhs, rhs); -} - -/*******************************************************************\ - -Function: path_symext::assign_rec - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void path_symext::assign_rec( - path_symex_statet &state, - exprt::operandst &guard, - const exprt &ssa_lhs, - const exprt &ssa_rhs) -{ - // const typet &ssa_lhs_type=state.var_map.ns.follow(ssa_lhs.type()); - - #ifdef DEBUG - std::cout << "assign_rec: " << ssa_lhs.pretty() << std::endl; - // std::cout << "ssa_lhs_type: " << ssa_lhs_type.id() << std::endl; - #endif - - if(ssa_lhs.id()==ID_symbol) - { - // These are expected to be SSA symbols - assert(ssa_lhs.get_bool(ID_C_SSA_symbol)); - - const symbol_exprt &symbol_expr=to_symbol_expr(ssa_lhs); - const irep_idt &full_identifier=symbol_expr.get(ID_C_full_identifier); - - #ifdef DEBUG - const irep_idt &ssa_identifier=symbol_expr.get_identifier(); - std::cout << "SSA symbol identifier: " << ssa_identifier << std::endl; - std::cout << "full identifier: " << full_identifier << std::endl; - #endif - - var_mapt::var_infot &var_info=state.var_map[full_identifier]; - assert(var_info.full_identifier==full_identifier); - - // increase the SSA counter and produce new SSA symbol expression - var_info.increment_ssa_counter(); - symbol_exprt new_lhs=var_info.ssa_symbol(); - - #ifdef DEBUG - std::cout << "new_lhs: " << new_lhs.get_identifier() << std::endl; - #endif - - // record new state of lhs - { - // reference is not stable - path_symex_statet::var_statet &var_state=state.get_var_state(var_info); - var_state.ssa_symbol=new_lhs; - } - - // rhs nil means non-det assignment - if(ssa_rhs.is_nil()) - { - path_symex_statet::var_statet &var_state=state.get_var_state(var_info); - var_state.value=nil_exprt(); - } - else - { - // consistency check - if(!base_type_eq(ssa_rhs.type(), new_lhs.type(), state.var_map.ns)) - { - #ifdef DEBUG - std::cout << "ssa_rhs: " << ssa_rhs.pretty() << std::endl; - std::cout << "new_lhs: " << new_lhs.pretty() << std::endl; - #endif - throw "assign_rec got different types"; - } - - // record the step - state.record_step(); - path_symex_stept &step=*state.history; - - if(!guard.empty()) - step.guard=conjunction(guard); - step.full_lhs=ssa_lhs; - step.ssa_lhs=new_lhs; - step.ssa_rhs=ssa_rhs; - - // propagate the rhs? - path_symex_statet::var_statet &var_state=state.get_var_state(var_info); - var_state.value=propagate(ssa_rhs)?ssa_rhs:nil_exprt(); - } - } - else if(ssa_lhs.id()==ID_member) - { - #ifdef DEBUG - std::cout << "assign_rec ID_member" << std::endl; - #endif - - const member_exprt &ssa_lhs_member_expr=to_member_expr(ssa_lhs); - const exprt &struct_op=ssa_lhs_member_expr.struct_op(); - - const typet &compound_type= - state.var_map.ns.follow(struct_op.type()); - - if(compound_type.id()==ID_struct) - { - // We flatten the top-level structs, so this one is inside an - // array or a union. - - exprt member_name(ID_member_name); - member_name.set( - ID_component_name, - ssa_lhs_member_expr.get_component_name()); - - with_exprt new_rhs(struct_op, member_name, ssa_rhs); - - assign_rec(state, guard, struct_op, new_rhs); - } - else if(compound_type.id()==ID_union) - { - // rewrite into byte_extract, and do again - exprt offset=from_integer(0, index_type()); - - byte_extract_exprt - new_lhs(byte_update_id(), struct_op, offset, ssa_rhs.type()); - - assign_rec(state, guard, new_lhs, ssa_rhs); - } - else - throw "assign_rec: member expects struct or union type"; - } - else if(ssa_lhs.id()==ID_index) - { - #ifdef DEBUG - std::cout << "assign_rec ID_index" << std::endl; - #endif - - throw "unexpected array index on lhs"; - } - else if(ssa_lhs.id()==ID_dereference) - { - #ifdef DEBUG - std::cout << "assign_rec ID_dereference" << std::endl; - #endif - - throw "unexpected dereference on lhs"; - } - else if(ssa_lhs.id()==ID_if) - { - #ifdef DEBUG - std::cout << "assign_rec ID_if" << std::endl; - #endif - - const if_exprt &lhs_if_expr=to_if_expr(ssa_lhs); - exprt cond=lhs_if_expr.cond(); - - // true - guard.push_back(cond); - assign_rec(state, guard, lhs_if_expr.true_case(), ssa_rhs); - guard.pop_back(); - - // false - guard.push_back(not_exprt(cond)); - assign_rec(state, guard, lhs_if_expr.false_case(), ssa_rhs); - guard.pop_back(); - } - else if(ssa_lhs.id()==ID_byte_extract_little_endian || - ssa_lhs.id()==ID_byte_extract_big_endian) - { - #ifdef DEBUG - std::cout << "assign_rec ID_byte_extract" << std::endl; - #endif - - const byte_extract_exprt &byte_extract_expr= - to_byte_extract_expr(ssa_lhs); - - // assignment to byte_extract operators: - // turn into byte_update operator - - irep_idt new_id; - - if(ssa_lhs.id()==ID_byte_extract_little_endian) - new_id=ID_byte_update_little_endian; - else if(ssa_lhs.id()==ID_byte_extract_big_endian) - new_id=ID_byte_update_big_endian; - else - assert(false); - - byte_update_exprt new_rhs(new_id); - - new_rhs.type()=byte_extract_expr.op().type(); - new_rhs.op()=byte_extract_expr.op(); - new_rhs.offset()=byte_extract_expr.offset(); - new_rhs.value()=ssa_rhs; - - const exprt new_lhs=byte_extract_expr.op(); - - assign_rec(state, guard, new_lhs, new_rhs); - } - else if(ssa_lhs.id()==ID_struct) - { - const struct_typet &struct_type= - to_struct_type(state.var_map.ns.follow(ssa_lhs.type())); - const struct_typet::componentst &components= - struct_type.components(); - - // split up into components - const exprt::operandst &operands=ssa_lhs.operands(); - - assert(operands.size()==components.size()); - - for(std::size_t i=0; i &further_states) -{ - #ifdef DEBUG - std::cout << "function_call_rec: " << function.pretty() << std::endl; - #endif - - if(function.id()==ID_symbol) - { - const irep_idt &function_identifier= - to_symbol_expr(function).get_identifier(); - - // find the function - locst::function_mapt::const_iterator f_it= - state.locs.function_map.find(function_identifier); - - if(f_it==state.locs.function_map.end()) - throw - "failed to find `"+id2string(function_identifier)+ - "' in function_map"; - - const locst::function_entryt &function_entry=f_it->second; - - loc_reft function_entry_point=function_entry.first_loc; - - // do we have a body? - if(function_entry_point==loc_reft()) - { - // no body - - // this is a skip - if(call.lhs().is_not_nil()) - assign(state, call.lhs(), nil_exprt()); - - state.next_pc(); - return; - } - - // push a frame on the call stack - path_symex_statet::threadt &thread= - state.threads[state.get_current_thread()]; - thread.call_stack.push_back(path_symex_statet::framet()); - thread.call_stack.back().current_function=function_identifier; - thread.call_stack.back().return_location=thread.pc.next_loc(); - thread.call_stack.back().return_lhs=call.lhs(); - thread.call_stack.back().saved_local_vars=thread.local_vars; - - - const code_typet &code_type=function_entry.type; - - const code_typet::parameterst &function_parameters=code_type.parameters(); - - const exprt::operandst &call_arguments=call.arguments(); - - // now assign the argument values to parameters - for(std::size_t i=0; iguard=not_exprt(guard); - function_call_rec( - further_states.back(), call, if_expr.false_case(), further_states); - } - - // do the true-case in 'state' - { - state.record_branch_step(true); - state.history->guard=guard; - function_call_rec(state, call, if_expr.true_case(), further_states); - } - } - } - else - // NOLINTNEXTLINE(readability/throw) as message is correctly uppercase - throw "TODO: function_call "+function.id_string(); -} - -/*******************************************************************\ - -Function: path_symext::return_from_function - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void path_symext::return_from_function( - path_symex_statet &state, - const exprt &return_value) -{ - path_symex_statet::threadt &thread=state.threads[state.get_current_thread()]; - - // returning from very last function? - if(thread.call_stack.empty()) - { - state.disable_current_thread(); - } - else - { - // update statistics - state.recursion_map[thread.call_stack.back().current_function]--; - - // set PC to return location - thread.pc=thread.call_stack.back().return_location; - - // assign the return value - if(return_value.is_not_nil() && - thread.call_stack.back().return_lhs.is_not_nil()) - assign(state, thread.call_stack.back().return_lhs, return_value); - - thread.call_stack.pop_back(); - } -} - -/*******************************************************************\ - -Function: path_symext::do_goto - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void path_symext::do_goto( - path_symex_statet &state, - std::list &further_states) -{ - const goto_programt::instructiont &instruction= - *state.get_instruction(); - - if(instruction.is_backwards_goto()) - { - // we keep a statistic on how many times we execute backwards gotos - state.unwinding_map[state.pc()]++; - } - - const loct &loc=state.locs[state.pc()]; - assert(!loc.branch_target.is_nil()); - - exprt guard=state.read(instruction.guard); - - if(guard.is_true()) // branch taken always - { - state.record_branch_step(true); - state.set_pc(loc.branch_target); - return; // we are done - } - -#ifdef PATH_SYMEX_FORK - pid_t pid=-1; -#endif - - if(!guard.is_false()) - { - // branch taken case - -#ifdef PATH_SYMEX_FORK - pid=fork(); - if(pid==0) - { - // "state" is stored in "further_states" - assert(!further_states.empty()); - - // child process explores paths starting from the - // new state thereby partitioning the search space - std::list::iterator - s_it=further_states.begin(), s_end=further_states.end(); - while(s_it!=s_end) - { - if(&(*s_it)!=&state) - // iterators in std::list are stable - s_it=further_states.erase(s_it); - else - ++s_it; - } - - assert(further_states.size()==1); - - // branch not taken case - state.record_branch_step(false); - state.set_pc(loc.branch_target); - state.history->guard=guard; - } -#endif - -#ifdef PATH_SYMEX_FORK - // forking failed so continue as if PATH_SYMEX_FORK were undefined - if(pid==-1) // NOLINT(readability/braces) -#endif - { -#ifdef PATH_SYMEX_LAZY_STATE - // lazily copy the state into 'further_states' - further_states.push_back(path_symex_statet::lazy_copy(state)); - further_states.back().record_true_branch(); -#else - // eagerly copy the state into 'further_states' - further_states.push_back(state); - further_states.back().record_branch_step(true); - further_states.back().set_pc(loc.branch_target); - further_states.back().history->guard=guard; -#endif - } - } - -#ifdef PATH_SYMEX_FORK - // parent process (regardless of any possible fork errors) - // should finish to explore all current 'further_states' - if(pid!=0) // NOLINT(readability/braces) -#endif - { - // branch not taken case - exprt negated_guard=not_exprt(guard); - state.record_branch_step(false); - state.next_pc(); - state.history->guard=negated_guard; - } -} - -/*******************************************************************\ - -Function: path_symext::do_goto - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void path_symext::do_goto( - path_symex_statet &state, - bool taken) -{ - state.record_step(); - - const goto_programt::instructiont &instruction= - *state.get_instruction(); - - if(instruction.is_backwards_goto()) - { - // we keep a statistic on how many times we execute backwards gotos - state.unwinding_map[state.pc()]++; - } - - exprt guard=state.read(instruction.guard); - - if(taken) - { - // branch taken case - const loct &loc=state.locs[state.pc()]; - assert(!loc.branch_target.is_nil()); - state.set_pc(loc.branch_target); - state.history->guard=guard; - } - else - { - // branch not taken case - exprt negated_guard=not_exprt(guard); - state.next_pc(); - state.history->guard=negated_guard; - } -} - -/*******************************************************************\ - -Function: path_symext::operator() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void path_symext::operator()( - path_symex_statet &state, - std::list &further_states) -{ - const goto_programt::instructiont &instruction= - *state.get_instruction(); - - #ifdef DEBUG - std::cout << "path_symext::operator(): " << instruction.type - << std::endl; - #endif - - switch(instruction.type) - { - case END_FUNCTION: - // pop the call stack - state.record_step(); - return_from_function(state, nil_exprt()); - break; - - case RETURN: - // pop the call stack - { - state.record_step(); - exprt return_val=instruction.code.operands().size()==1? - instruction.code.op0():nil_exprt(); - return_from_function(state, return_val); - } - break; - - case START_THREAD: - { - const loct &loc=state.locs[state.pc()]; - assert(!loc.branch_target.is_nil()); - - state.record_step(); - state.next_pc(); - - // ordering of the following matters due to vector instability - path_symex_statet::threadt &new_thread=state.add_thread(); - path_symex_statet::threadt &old_thread= - state.threads[state.get_current_thread()]; - new_thread.pc=loc.branch_target; - new_thread.local_vars=old_thread.local_vars; - } - break; - - case END_THREAD: - state.record_step(); - state.disable_current_thread(); - break; - - case GOTO: - if(state.is_lazy()) - do_goto(state, state.restore_branch()); - else - do_goto(state, further_states); - break; - - case CATCH: - // ignore for now - state.record_step(); - state.next_pc(); - break; - - case THROW: - state.record_step(); - throw "THROW not yet implemented"; // NOLINT(readability/throw) - - case ASSUME: - state.record_step(); - state.next_pc(); - if(instruction.guard.is_false()) - state.disable_current_thread(); - else - { - exprt guard=state.read(instruction.guard); - state.history->guard=guard; - } - break; - - case ASSERT: - case SKIP: - case LOCATION: - case DEAD: - state.record_step(); - state.next_pc(); - break; - - case DECL: - // assigning an RHS of NIL means 'nondet' - assign(state, to_code_decl(instruction.code).symbol(), nil_exprt()); - state.next_pc(); - break; - - case ATOMIC_BEGIN: - if(state.inside_atomic_section) - throw "nested ATOMIC_BEGIN"; - - state.record_step(); - state.next_pc(); - state.inside_atomic_section=true; - break; - - case ATOMIC_END: - if(!state.inside_atomic_section) - throw "ATOMIC_END unmatched"; // NOLINT(readability/throw) - - state.record_step(); - state.next_pc(); - state.inside_atomic_section=false; - break; - - case ASSIGN: - assign(state, to_code_assign(instruction.code)); - state.next_pc(); - break; - - case FUNCTION_CALL: - state.record_step(); - function_call( - state, to_code_function_call(instruction.code), further_states); - break; - - case OTHER: - state.record_step(); - - { - const codet &code=instruction.code; - const irep_idt &statement=code.get_statement(); - - if(statement==ID_expression) - { - // like SKIP - } - else if(statement==ID_printf) - { - // ignore for now (should record stuff printed) - } - else if(statement==ID_asm) - { - // ignore for now - } - else if(statement==ID_fence) - { - // ignore for SC - } - else if(statement==ID_input) - { - // just needs to be recorded - } - else - throw "unexpected OTHER statement: "+id2string(statement); - } - - state.next_pc(); - break; - - default: - throw "path_symext: unexpected instruction"; - } -} - -/*******************************************************************\ - -Function: path_symext::operator() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void path_symext::operator()(path_symex_statet &state) -{ - std::list further_states; - operator()(state, further_states); - if(!further_states.empty()) - throw "path_symext got unexpected further states"; -} - -/*******************************************************************\ - -Function: path_symex - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void path_symex( - path_symex_statet &state, - std::list &further_states) -{ - // "state" is stored in "further_states" - assert(!further_states.empty()); - - path_symext path_symex; - path_symex(state, further_states); -} - -/*******************************************************************\ - -Function: path_symex - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void path_symex(path_symex_statet &state) -{ - path_symext path_symex; - path_symex(state); -} - -/*******************************************************************\ - -Function: path_symex_goto - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void path_symex_goto( - path_symex_statet &state, - bool taken) -{ - path_symext path_symex; - path_symex.do_goto(state, taken); -} - -/*******************************************************************\ - -Function: path_symex_assert_fail - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void path_symex_assert_fail(path_symex_statet &state) -{ - path_symext path_symex; - path_symex.do_assert_fail(state); -} diff --git a/src/aa-path-symex/path_symex.h b/src/aa-path-symex/path_symex.h deleted file mode 120000 index 538d30846d4..00000000000 --- a/src/aa-path-symex/path_symex.h +++ /dev/null @@ -1 +0,0 @@ -../path-symex/path_symex.h \ No newline at end of file diff --git a/src/aa-path-symex/path_symex_state.cpp b/src/aa-path-symex/path_symex_state.cpp deleted file mode 100644 index b0c502f639d..00000000000 --- a/src/aa-path-symex/path_symex_state.cpp +++ /dev/null @@ -1,799 +0,0 @@ -/*******************************************************************\ - -Module: State of path-based symbolic simulator - -Author: Daniel Kroening, kroening@kroening.com - Alex Horn, alex.horn@cs.ox.ac.uk - -\*******************************************************************/ - -#include -#include -#include - -#include - -#include - -#include -#include - -#include "path_symex_state.h" - -// #define DEBUG - -#ifdef DEBUG -#include -#include -#endif - -/*******************************************************************\ - -Function: initial_state - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -path_symex_statet initial_state( - var_mapt &var_map, - const locst &locs, - path_symex_historyt &path_symex_history) -{ - return path_symex_statet( - var_map, - locs, - path_symex_step_reft(path_symex_history), - path_symex_statet::branchest()); -} - -/*******************************************************************\ - -Function: path_symex_statet::output - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -goto_programt::const_targett path_symex_statet::get_instruction() const -{ - assert(current_thread " << tmp.pretty() << std::endl; - #endif - - return tmp5; -} - -/*******************************************************************\ - -Function: path_symex_statet::instantiate_rec - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -exprt path_symex_statet::instantiate_rec( - const exprt &src, - bool propagate) -{ - #ifdef DEBUG - std::cout << "instantiate_rec: " - << from_expr(var_map.ns, "", src) << std::endl; - #endif - - const typet &src_type=var_map.ns.follow(src.type()); - - if(src_type.id()==ID_struct) // src is a struct - { - const struct_typet &struct_type=to_struct_type(src_type); - const struct_typet::componentst &components=struct_type.components(); - - struct_exprt result(src.type()); - result.operands().resize(components.size()); - - // split it up into components - for(unsigned i=0; ithread_nr!=current_thread) - no_thread_interleavings++; - - // update our statistics - depth++; - - // add the step - history.generate_successor(); - path_symex_stept &step=*history; - - // copy PC - assert(current_threadis_goto()); - -#ifdef PATH_SYMEX_LAZY_BRANCH - if(!branches.empty() || history.is_nil()) -#endif - { - // get_branches() relies on branch decisions - branches.push_back(taken); - - if(get_instruction()->is_goto()) - { - branches_restore++; - } - else - { - assert(pc()==locs.entry_loc); - assert(history.is_nil()); - } - } - - record_step(); -} - -/*******************************************************************\ - -Function: path_symex_statet::is_feasible - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -bool path_symex_statet::is_feasible( - decision_proceduret &decision_procedure) const -{ - // feed path constraint to decision procedure - decision_procedure << history; - - // check whether SAT - switch(decision_procedure()) - { - case decision_proceduret::D_SATISFIABLE: return true; - - case decision_proceduret::D_UNSATISFIABLE: return false; - - case decision_proceduret::D_ERROR: throw "error from decision procedure"; - } - - return true; // not really reachable -} - -/*******************************************************************\ - -Function: path_symex_statet::check_assertion - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -bool path_symex_statet::check_assertion( - decision_proceduret &decision_procedure) -{ - const goto_programt::instructiont &instruction=*get_instruction(); - - // assert that this is an assertion - assert(instruction.is_assert()); - - // the assertion in SSA - exprt assertion=read(instruction.guard); - - // trivial? - if(assertion.is_true()) - return true; // no error - - // the path constraint - decision_procedure << history; - - // negate the assertion - decision_procedure.set_to(assertion, false); - - // check whether SAT - switch(decision_procedure.dec_solve()) - { - case decision_proceduret::D_SATISFIABLE: - return false; // error - - case decision_proceduret::D_UNSATISFIABLE: - return true; // no error - - default: - throw "error from decision procedure"; - } - - return true; // not really reachable -} diff --git a/src/aa-path-symex/path_symex_state.h b/src/aa-path-symex/path_symex_state.h deleted file mode 100644 index dd10e43d8da..00000000000 --- a/src/aa-path-symex/path_symex_state.h +++ /dev/null @@ -1,350 +0,0 @@ -/*******************************************************************\ - -Module: State of path-based symbolic simulator - -Author: Daniel Kroening, kroening@kroening.com - Alex Horn, alex.horn@cs.ox.ac.uk - -\*******************************************************************/ - -#ifndef CPROVER_AA_PATH_SYMEX_PATH_SYMEX_STATE_H -#define CPROVER_AA_PATH_SYMEX_PATH_SYMEX_STATE_H - -#include - -#include -#include -#include - -// These variables may be defined in this header file only because -// it is (transitively) included by many essential path-symex files. -// In addition, since these variables determine how states are -// handled, it makes sense to define them in this header file. -#define PATH_SYMEX_LAZY_STATE -#define PATH_SYMEX_FORK - -// This flag is particularly useful for regression testing purposes. -// -// If PATH_SYMEX_LAZY_BRANCH is undefined, then branches are always -// recorded and the control logic in get_branches() is bypassed. But -// the output of path_search() should be identical in this setting; -// otherwise, the assumptions about GOTO programs or the history -// data structure should be revisited. -#define PATH_SYMEX_LAZY_BRANCH - -// check POSIX-compliance -#ifdef PATH_SYMEX_FORK -#if defined(__linux__) || \ - defined(__FreeBSD_kernel__) || \ - defined(__GNU__) || \ - defined(__unix__) || \ - defined(__CYGWIN__) || \ - defined(__MACH__) -#include -#include -#else -#error Cannot define PATH_SYMEX_FORK on non-POSIX systems -#endif -#endif - -class path_symex_statet -{ -public: - // use symbolic execution to repopulate composite fields - - // TODO: consider std::bitset or chaining to shrink state size - typedef std::vector branchest; - - // if _branches.empty(), then initial state; otherwise, lazy state - - // \post: pc() is the entry point to the program under scrutiny - path_symex_statet( - var_mapt &_var_map, - const locst &_locs, - path_symex_step_reft _history, - const branchest &_branches): - var_map(_var_map), - locs(_locs), - shared_vars(), - threads(), - inside_atomic_section(), - history(_history), - unwinding_map(), - recursion_map(), - branches(_branches), - branches_restore(0), - current_thread(0), - no_thread_interleavings(0), - depth(0) - { - path_symex_statet::threadt &thread=add_thread(); - thread.pc=locs.entry_loc; // reset its PC - } - - // like initial state except that branches are copied from "other" - // and history will be 'nil' - static path_symex_statet lazy_copy(path_symex_statet &other) - { - // allow compiler to use RVO - return path_symex_statet( - other.var_map, - other.locs, - path_symex_step_reft(), - other.get_branches()); - } - - // These are tied to a particular var_map - // and a particular program. - var_mapt &var_map; - const locst &locs; - - // the value of a variable - struct var_statet - { - // it's a given explicit value or a symbol with given identifier - exprt value; - symbol_exprt ssa_symbol; - - // for uninterpreted functions or arrays we maintain an index set - typedef std::set index_sett; - index_sett index_set; - - var_statet(): - value(nil_exprt()), - ssa_symbol(irep_idt()) - { - } - }; - - // the values of the shared variables - typedef std::vector var_valt; - var_valt shared_vars; - - // procedure frame - struct framet - { - irep_idt current_function; - loc_reft return_location; - exprt return_lhs; - var_valt saved_local_vars; - }; - - // call stack - typedef std::vector call_stackt; - - // the state of a thread - struct threadt - { - public: - loc_reft pc; - call_stackt call_stack; // the call stack - var_valt local_vars; // thread-local variables - bool active; - - threadt():active(true) - { - } - }; - - typedef std::vector threadst; - threadst threads; - - // warning: reference is not stable - var_statet &get_var_state(const var_mapt::var_infot &var_info); - - bool inside_atomic_section; - - unsigned get_current_thread() const - { - return current_thread; - } - - void set_current_thread(unsigned _thread) - { - current_thread=_thread; - } - - goto_programt::const_targett get_instruction() const; - - // branch taken case - void record_true_branch() - { - branches.push_back(true); - } - - // branch not taken case - void record_false_branch() - { - branches.push_back(false); - } - - bool is_lazy() const - { - return branches_restore < branches.size(); - } - - // returns branch direction that should be taken - bool restore_branch() - { - assert(is_lazy()); - return branches[branches_restore++]; - } - - bool is_executable() const - { - return !threads.empty() && - threads[current_thread].active; - } - - // execution history - path_symex_step_reft history; - - // adds an entry to the history - void record_step(); - - // like record_step() except that branch decision is also recorded - void record_branch_step(bool taken); - - // various state transformers - - threadt &add_thread() - { - threads.resize(threads.size()+1); - return threads.back(); - } - - void disable_current_thread() - { - threads[current_thread].active=false; - } - - loc_reft pc() const - { - return threads[current_thread].pc; - } - - void next_pc() - { - threads[current_thread].pc.increase(); - } - - void set_pc(loc_reft new_pc) - { - threads[current_thread].pc=new_pc; - } - - // output - void output(std::ostream &out) const; - void output(const threadt &thread, std::ostream &out) const; - - // instantiate expressions with propagation - exprt read(const exprt &src) - { - return read(src, true); - } - - // instantiate without constant propagation - exprt read_no_propagate(const exprt &src) - { - return read(src, false); - } - - exprt dereference_rec(const exprt &src, bool propagate); - - std::string array_index_as_string(const exprt &) const; - - unsigned get_no_thread_interleavings() const - { - return no_thread_interleavings; - } - - unsigned get_depth() const - { - return depth; - } - - bool is_feasible(class decision_proceduret &) const; - - bool check_assertion(class decision_proceduret &); - - // counts how many times we have executed backwards edges - typedef std::map unwinding_mapt; - unwinding_mapt unwinding_map; - - // similar for recursive function calls - typedef std::map recursion_mapt; - recursion_mapt recursion_map; - -protected: - branchest branches; - branchest::size_type branches_restore; - - // On first call, O(N) where N is the length of the execution path - // leading to this state. Subsequent calls run in constant time. - const branchest &get_branches() - { - if(!branches.empty() || history.is_nil()) - return branches; - - // Contrarily, suppose this state is lazy. Since we did not - // return above, branches.empty(). By definition of is_lazy(), - // branches_restore must have been a negative number. Since - // its type is unsigned, however, this is impossible. - assert(!is_lazy()); - - path_symex_step_reft step_ref=history; - assert(!step_ref.is_nil()); - loc_reft next_loc_ref=pc(); - for(;;) - { - if(step_ref.is_nil()) - break; - - const loct &loc=locs[step_ref->pc]; - if(loc.target->is_goto()) - { - branches.push_back(loc.branch_target==next_loc_ref); - assert(branches.back() || step_ref->pc.next_loc()==next_loc_ref); - } - - next_loc_ref=step_ref->pc; - step_ref=step_ref->predecessor; - } - - // preserve non-laziness of this state (see first assertion) - branches_restore=branches.size(); - - // TODO: add "path_symex_step::branch_depth" field so we can - // reserve() the right capacity of vector and avoid reverse(). - std::reverse(branches.begin(), branches.end()); - - return branches; - } - - unsigned current_thread; - unsigned no_thread_interleavings; - unsigned depth; - - exprt read( - const exprt &src, - bool propagate); - - exprt instantiate_rec( - const exprt &src, - bool propagate); - - exprt instantiate_rec_address( - const exprt &src, - bool propagate); - - exprt read_symbol_member_index( - const exprt &src, - bool propagate); -}; - -path_symex_statet initial_state( - var_mapt &var_map, - const locst &locs, - path_symex_historyt &); - -#endif // CPROVER_AA_PATH_SYMEX_PATH_SYMEX_STATE_H diff --git a/src/aa-symex/Makefile b/src/aa-symex/Makefile deleted file mode 100644 index a5e2b0ad5d8..00000000000 --- a/src/aa-symex/Makefile +++ /dev/null @@ -1,68 +0,0 @@ -SRC = path_search.cpp - -OBJ += ../ansi-c/ansi-c$(LIBEXT) \ - ../linking/linking$(LIBEXT) \ - ../big-int/big-int$(LIBEXT) \ - ../goto-programs/goto-programs$(LIBEXT) \ - ../analyses/analyses$(LIBEXT) \ - ../langapi/langapi$(LIBEXT) \ - ../xmllang/xmllang$(LIBEXT) \ - ../assembler/assembler$(LIBEXT) \ - ../solvers/solvers$(LIBEXT) \ - ../util/util$(LIBEXT) \ - ../goto-symex/adjust_float_expressions$(OBJEXT) \ - ../goto-symex/rewrite_union$(OBJEXT) \ - ../pointer-analysis/dereference$(OBJEXT) \ - ../goto-instrument/cover$(OBJEXT) \ - ../aa-path-symex/aa-path-symex$(LIBEXT) \ - ../symex/symex_main$(OBJEXT) \ - ../symex/symex_parse_options$(OBJEXT) \ - ../symex/symex_cover$(OBJEXT) \ - ../path-symex/locs$(OBJEXT) ../path-symex/var_map$(OBJEXT) \ - ../path-symex/path_symex_history$(OBJEXT) - -INCLUDES= -I .. - -LIBS = - -include ../config.inc -include ../common - -CLEANFILES = symex$(EXEEXT) - -all: symex$(EXEEXT) - -ifneq ($(wildcard ../bv_refinement/Makefile),) - OBJ += ../bv_refinement/bv_refinement$(LIBEXT) - CP_CXXFLAGS += -DHAVE_BV_REFINEMENT -endif - -ifneq ($(wildcard ../cpp/Makefile),) - OBJ += ../cpp/cpp$(LIBEXT) - CP_CXXFLAGS += -DHAVE_CPP -endif - -ifneq ($(wildcard ../java_bytecode/Makefile),) - OBJ += ../java_bytecode/java_bytecode$(LIBEXT) - CP_CXXFLAGS += -DHAVE_JAVA_BYTECODE -endif - -ifneq ($(wildcard ../specc/Makefile),) - OBJ += ../specc/specc$(LIBEXT) - CP_CXXFLAGS += -DHAVE_SPECC -endif - -ifneq ($(wildcard ../php/Makefile),) - OBJ += ../php/php$(LIBEXT) - CP_CXXFLAGS += -DHAVE_PHP -endif - -############################################################################### - -symex$(EXEEXT): $(OBJ) - $(LINKBIN) - -.PHONY: symex-mac-signed - -symex-mac-signed: cbmc$(EXEEXT) - strip symex$(EXEEXT) ; codesign -v -s $(OSX_IDENTITY) symex$(EXEEXT) diff --git a/src/aa-symex/path_search.cpp b/src/aa-symex/path_search.cpp deleted file mode 100644 index 5bfa680177f..00000000000 --- a/src/aa-symex/path_search.cpp +++ /dev/null @@ -1,517 +0,0 @@ -/*******************************************************************\ - -Module: Path-based Symbolic Execution - -Author: Daniel Kroening, kroening@kroening.com - Alex Horn, alex.horn@cs.ox.ac.uk - -\*******************************************************************/ - -#include -#include - -#include -#include - -#include -#include - -#include "path_search.h" - -#ifdef PATH_SYMEX_FORK -// we've already check that the platform is (mostly) POSIX-compliant -#include -#endif - -/*******************************************************************\ - -Function: path_searcht::operator() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -path_searcht::resultt path_searcht::operator()( - const goto_functionst &goto_functions) -{ -#ifdef PATH_SYMEX_FORK - // Disable output because there is no meaningful way - // to write text when multiple path_search processes - // run concurrently. This could be remedied by piping - // to individual files or inter-process communication, - // a performance bottleneck, however. - null_message_handlert null_message; - set_message_handler(null_message); -#endif - - locst locs(ns); - var_mapt var_map(ns); - - locs.build(goto_functions); - - // this is the container for the history-forest - path_symex_historyt history; - - queue.push_back(initial_state(var_map, locs, history)); - - // set up the statistics - number_of_instructions=0; - number_of_dropped_states=0; - number_of_paths=0; - number_of_VCCs=0; - number_of_VCCs_after_simplification=0; - number_of_failed_properties=0; - number_of_fast_forward_steps=0; - - // stop the time - start_time=current_time(); - - initialize_property_map(goto_functions); - - while(!queue.empty()) - { - // Pick a state from the queue, - // according to some heuristic. - queuet::iterator state=pick_state(); - - // fast forwarding required? - if(state->is_lazy()) - { - assert(state->is_executable()); - assert(state->history.is_nil()); - - // keep allocated memory, this is faster than - // instantiating a new empty vector and map - history.clear(); - var_map.clear(); - state->history=path_symex_step_reft(history); - - // restore all fields of a lazy state by symbolic - // execution along previously recorded branches - const queuet::size_type queue_size=queue.size(); - do - { - number_of_fast_forward_steps++; - - path_symex(*state, queue); -#ifdef PATH_SYMEX_OUTPUT - status() << "Fast forward thread " << state->get_current_thread() - << "/" << state->threads.size() - << " PC " << state->pc() << messaget::eom; -#endif - } - while(state->is_lazy() && state->is_executable()); - assert(queue.size() == queue_size); - } - - // TODO: check lazy states before fast forwarding, or perhaps it - // is better to even check before inserting into queue - if(drop_state(*state)) - { - number_of_dropped_states++; - queue.erase(state); - continue; - } - - if(!state->is_executable()) - { - queue.erase(state); - continue; - } - - // count only executable instructions - number_of_instructions++; - -#ifdef PATH_SYMEX_OUTPUT - status() << "Queue " << queue.size() - << " thread " << state->get_current_thread() - << "/" << state->threads.size() - << " PC " << state->pc() << messaget::eom; -#endif - - // an error, possibly? - if(state->get_instruction()->is_assert()) - { - if(show_vcc) - do_show_vcc(*state); - else - { - check_assertion(*state); - - // all assertions failed? - if(number_of_failed_properties==property_map.size()) - break; - } - } - -#ifdef PATH_SYMEX_FORK - if(try_await()) - { - debug() << "Child process has terminated " - "so exit parent" << messaget::eom; - break; - } -#endif - - // execute and record whether a "branch" occurred - const queuet::size_type queue_size = queue.size(); - path_symex(*state, queue); - - assert(queue_size <= queue.size()); - number_of_paths += (queue.size() - queue_size); - } - -#ifdef PATH_SYMEX_FORK - int exit_status=await(); - if(exit_status==0 && number_of_failed_properties!=0) - { - // the eldest child process (if any) reports found bugs - report_statistics(); - return UNSAFE; - } - else - { - // either a child found and reported a bug or - // the parent's search partition is safe - switch(exit_status) - { - case 0: return SAFE; - case 10: return UNSAFE; - default: return ERROR; - } - } -#else - report_statistics(); - - return number_of_failed_properties==0?SAFE:UNSAFE; -#endif -} - -#ifdef PATH_SYMEX_FORK -/*******************************************************************\ - -Function: path_searcht::await() - - Inputs: - - Outputs: returns zero if and only if every child process succeeds; - otherwise, the error of exactly one child is returned - - Purpose: POSIX-compliant (possibly blocking) wait on child - processes, writes to error() if anything goes wrong; - any earlier calls to try_await() do not affect await() - -\*******************************************************************/ - -int path_searcht::await() -{ - int status; - for(;;) - { - // a process' entries for its child processes are deleted after - // the first call to waitpid(). When waitpid() is called again - // it returns -1 and errno is set to ECHILD. - pid_t pid=wait(&status); - if(pid==-1) - { - if(errno==ECHILD) - break; // no more child processes - } - else - { - if(!WIFEXITED(status) || WEXITSTATUS(status)!=0) - { - debug() << "PID " << pid << " failed, return code " - << WEXITSTATUS(status) << messaget::eom; - - return WEXITSTATUS(status); - } - } - } - - return 0; -} - -/*******************************************************************\ - -Function: path_searcht::try_await() - - Inputs: - - Outputs: returns true if and only if at least one child process - has terminated - - Purpose: POSIX-compliant nonblocking wait on child processes, - child's status is preserved for await() function - -\*******************************************************************/ - -bool path_searcht::try_await() -{ - int status; - pid_t pid=waitpid(-1, &status, WNOHANG | WNOWAIT); - return pid!=-1; -} -#endif - -/*******************************************************************\ - -Function: path_searcht::report_statistics - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void path_searcht::report_statistics() -{ - // report a bit - - status() << "Number of instructions: " - << number_of_instructions << messaget::eom; - - status() << "Number of dropped states: " - << number_of_dropped_states << messaget::eom; - - status() << "Number of paths: " - << number_of_paths << messaget::eom; - - status() << "Number of fast forward steps: " - << number_of_fast_forward_steps << messaget::eom; - - status() << "Generated " << number_of_VCCs << " VCC(s), " - << number_of_VCCs_after_simplification - << " remaining after simplification" - << messaget::eom; - - time_periodt total_time=current_time()-start_time; - status() << "Runtime: " << total_time << "s total, " - << sat_time << "s SAT" << messaget::eom; -} - -/*******************************************************************\ - -Function: path_searcht::pick_state - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -path_searcht::queuet::iterator path_searcht::pick_state() -{ - // Picking the first one is a DFS. - return queue.begin(); -} - -/*******************************************************************\ - -Function: path_searcht::do_show_vcc - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void path_searcht::do_show_vcc(statet &state) -{ - // keep statistics - number_of_VCCs++; - - const goto_programt::instructiont &instruction= - *state.get_instruction(); - - mstreamt &out=result(); - - if(instruction.source_location.is_not_nil()) - out << instruction.source_location << '\n'; - - if(instruction.source_location.get_comment()!="") - out << instruction.source_location.get_comment() << '\n'; - - unsigned count=1; - - std::vector steps; - state.history.build_history(steps); - - for(const auto &step_ref : steps) - { - if(step_ref->guard.is_not_nil()) - { - std::string string_value=from_expr(ns, "", step_ref->guard); - out << "{-" << count << "} " << string_value << '\n'; - count++; - } - - if(step_ref->ssa_rhs.is_not_nil()) - { - equal_exprt equality(step_ref->ssa_lhs, step_ref->ssa_rhs); - std::string string_value=from_expr(ns, "", equality); - out << "{-" << count << "} " << string_value << '\n'; - count++; - } - } - - out << "|--------------------------" << '\n'; - - exprt assertion=state.read(instruction.guard); - - out << "{" << 1 << "} " - << from_expr(ns, "", assertion) << '\n'; - - if(!assertion.is_true()) - number_of_VCCs_after_simplification++; - - out << eom; -} - -/*******************************************************************\ - -Function: path_searcht::drop_state - - Inputs: - - Outputs: - - Purpose: decide whether to drop a state - -\*******************************************************************/ - -bool path_searcht::drop_state(const statet &state) const -{ - // depth limit - if(depth_limit_set && state.get_depth()>depth_limit) - return true; - - // context bound - if(context_bound_set && state.get_no_thread_interleavings()>context_bound) - return true; - - - // unwinding limit -- loops - if(unwind_limit_set && state.get_instruction()->is_backwards_goto()) - { - for(const auto &loop_info : state.unwinding_map) - if(loop_info.second>unwind_limit) - return true; - } - - // unwinding limit -- recursion - if(unwind_limit_set && state.get_instruction()->is_function_call()) - { - for(const auto &rec_info : state.recursion_map) - if(rec_info.second>unwind_limit) - return true; - } - - return false; -} - -/*******************************************************************\ - -Function: path_searcht::check_assertion - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void path_searcht::check_assertion(statet &state) -{ - // keep statistics - number_of_VCCs++; - - const goto_programt::instructiont &instruction= - *state.get_instruction(); - - irep_idt property_name=instruction.source_location.get_property_id(); - property_entryt &property_entry=property_map[property_name]; - - if(property_entry.status==FAILURE) - return; // already failed - else if(property_entry.status==NOT_REACHED) - property_entry.status=SUCCESS; // well, for now! - - // the assertion in SSA - exprt assertion= - state.read(instruction.guard); - - if(assertion.is_true()) - return; // no error, trivially - - // keep statistics - number_of_VCCs_after_simplification++; - - status() << "Checking property " << property_name << eom; - - // take the time - absolute_timet sat_start_time=current_time(); - - satcheckt satcheck; - bv_pointerst bv_pointers(ns, satcheck); - - satcheck.set_message_handler(get_message_handler()); - bv_pointers.set_message_handler(get_message_handler()); - - if(!state.check_assertion(bv_pointers)) - { - build_goto_trace(state, bv_pointers, property_entry.error_trace); - property_entry.status=FAILURE; - number_of_failed_properties++; - } - - sat_time+=current_time()-sat_start_time; -} - -/*******************************************************************\ - -Function: path_searcht::initialize_property_map - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void path_searcht::initialize_property_map( - const goto_functionst &goto_functions) -{ - forall_goto_functions(it, goto_functions) - if(!it->second.is_inlined()) - { - const goto_programt &goto_program=it->second.body; - - forall_goto_program_instructions(i_it, goto_program) - { - if(!i_it->is_assert()) - continue; - - const source_locationt &source_location=i_it->source_location; - - irep_idt property_name=source_location.get_property_id(); - - property_entryt &property_entry=property_map[property_name]; - property_entry.status=NOT_REACHED; - property_entry.description=source_location.get_comment(); - property_entry.source_location=source_location; - } - } -} diff --git a/src/aa-symex/path_search.h b/src/aa-symex/path_search.h deleted file mode 100644 index 51c67ac93f0..00000000000 --- a/src/aa-symex/path_search.h +++ /dev/null @@ -1,119 +0,0 @@ -/*******************************************************************\ - -Module: Path-based Symbolic Execution - -Author: Daniel Kroening, kroening@kroening.com - Alex Horn, alex.horn@cs.ox.ac.uk - -\*******************************************************************/ - -#ifndef CPROVER_AA_SYMEX_PATH_SEARCH_H -#define CPROVER_AA_SYMEX_PATH_SEARCH_H - -#include - -#include - -#include - -class path_searcht:public safety_checkert -{ -public: - explicit path_searcht(const namespacet &_ns): - safety_checkert(_ns), - show_vcc(false), - depth_limit_set(false), // no limit - context_bound_set(false), - unwind_limit_set(false) - { - } - - virtual resultt operator()( - const goto_functionst &goto_functions); - - void set_depth_limit(unsigned limit) - { - depth_limit_set=true; - depth_limit=limit; - } - - void set_context_bound(unsigned limit) - { - context_bound_set=true; - context_bound=limit; - } - - void set_unwind_limit(unsigned limit) - { - unwind_limit_set=true; - unwind_limit=limit; - } - - bool show_vcc; - - // statistics - unsigned number_of_instructions; - unsigned number_of_dropped_states; - unsigned number_of_paths; - unsigned number_of_VCCs; - unsigned number_of_VCCs_after_simplification; - unsigned number_of_failed_properties; - unsigned number_of_fast_forward_steps; - absolute_timet start_time; - time_periodt sat_time; - - enum statust { NOT_REACHED, SUCCESS, FAILURE }; - - struct property_entryt - { - statust status; - irep_idt description; - goto_tracet error_trace; - source_locationt source_location; - - bool is_success() const { return status==SUCCESS; } - bool is_failure() const { return status==FAILURE; } - bool is_not_reached() const { return status==NOT_REACHED; } - }; - - typedef std::map property_mapt; - property_mapt property_map; - -protected: -#ifdef PATH_SYMEX_FORK - // blocks until child processes have terminated - int await(); - - // returns whether at least one child process has terminated - bool try_await(); -#endif - - typedef path_symex_statet statet; - - // State queue. Iterators are stable. - // The states most recently executed are at the head. - typedef std::list queuet; - queuet queue; - - // search heuristic - queuet::iterator pick_state(); - - bool execute(queuet::iterator state, const namespacet &); - - void check_assertion(statet &state); - void do_show_vcc(statet &state); - - bool drop_state(const statet &state) const; - - void report_statistics(); - - void initialize_property_map( - const goto_functionst &goto_functions); - - unsigned depth_limit; - unsigned context_bound; - unsigned unwind_limit; - bool depth_limit_set, context_bound_set, unwind_limit_set; -}; - -#endif // CPROVER_AA_SYMEX_PATH_SEARCH_H From fdd81210c9b1e98fa6c1085fc0ef7a13cbc2b9af Mon Sep 17 00:00:00 2001 From: Vlastimil Zeman Date: Mon, 27 Feb 2017 13:48:31 +0000 Subject: [PATCH 020/699] Fix failing travis tests after removal of aa-symex. --- .travis.yml | 2 +- src/Makefile | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6af73e31878..e8e19bc01ea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,4 +47,4 @@ script: make -C src minisat2-download && make -C src CXX=$COMPILER CXXFLAGS="-Wall -O2 -g -Werror -Wno-deprecated-register -pedantic -Wno-sign-compare" -j2 && env UBSAN_OPTIONS=print_stacktrace=1 make -C regression test && - make -C src CXX=$COMPILER CXXFLAGS=$FLAGS -j2 aa-symex.dir cegis.dir clobber.dir memory-models.dir musketeer.dir + make -C src CXX=$COMPILER CXXFLAGS=$FLAGS -j2 cegis.dir clobber.dir memory-models.dir musketeer.dir diff --git a/src/Makefile b/src/Makefile index 7b9e3a1d446..3a452b7fe09 100644 --- a/src/Makefile +++ b/src/Makefile @@ -44,8 +44,6 @@ symex.dir: languages goto-programs.dir pointer-analysis.dir \ goto-symex.dir linking.dir analyses.dir solvers.dir \ path-symex.dir goto-instrument.dir -aa-symex.dir: symex.dir aa-path-symex.dir - # building for a particular directory $(patsubst %, %.dir, $(DIRS)): From 895f8a69514a29da293225f51fb60590571ee0cd Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 24 Oct 2016 12:27:56 +0100 Subject: [PATCH 021/699] Skip already-loaded Java classes --- src/java_bytecode/java_bytecode_convert_class.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/java_bytecode/java_bytecode_convert_class.cpp b/src/java_bytecode/java_bytecode_convert_class.cpp index 8d42611bfe0..b62c5746765 100644 --- a/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/src/java_bytecode/java_bytecode_convert_class.cpp @@ -75,6 +75,13 @@ Function: java_bytecode_convert_classt::convert void java_bytecode_convert_classt::convert(const classt &c) { + std::string qualified_classname="java::"+id2string(c.name); + if(symbol_table.has_symbol(qualified_classname)) + { + debug() << "Skip class " << c.name << " (already loaded)" << eom; + return; + } + class_typet class_type; class_type.set_tag(c.name); @@ -107,7 +114,7 @@ void java_bytecode_convert_classt::convert(const classt &c) symbolt new_symbol; new_symbol.base_name=c.name; new_symbol.pretty_name=c.name; - new_symbol.name="java::"+id2string(c.name); + new_symbol.name=qualified_classname; class_type.set(ID_name, new_symbol.name); new_symbol.type=class_type; new_symbol.mode=ID_java; From 777d52e35548d2add1b46fb468b3534e19b4b2f6 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 1 Nov 2016 13:48:01 +0000 Subject: [PATCH 022/699] Convert Java methods only when they have a caller This means that library methods, for example, will often not be converted. For the time being virtual methods calls are handled simply, assuming that any class we know of that provides an override might be called. --- .../java_bytecode_convert_class.cpp | 35 ++++++--- .../java_bytecode_convert_class.h | 6 +- .../java_bytecode_convert_method.cpp | 57 +++++++++++++-- .../java_bytecode_convert_method.h | 12 ++- .../java_bytecode_convert_method_class.h | 12 ++- src/java_bytecode/java_bytecode_language.cpp | 73 ++++++++++++++++++- src/java_bytecode/java_entry_point.cpp | 8 +- src/java_bytecode/java_entry_point.h | 3 +- 8 files changed, 179 insertions(+), 27 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_class.cpp b/src/java_bytecode/java_bytecode_convert_class.cpp index b62c5746765..2036bcd9bce 100644 --- a/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/src/java_bytecode/java_bytecode_convert_class.cpp @@ -27,11 +27,13 @@ class java_bytecode_convert_classt:public messaget symbol_tablet &_symbol_table, message_handlert &_message_handler, bool _disable_runtime_checks, - size_t _max_array_length): + size_t _max_array_length, + lazy_methodst& _lm): messaget(_message_handler), symbol_table(_symbol_table), disable_runtime_checks(_disable_runtime_checks), - max_array_length(_max_array_length) + max_array_length(_max_array_length), + lazy_methods(_lm) { } @@ -52,6 +54,7 @@ class java_bytecode_convert_classt:public messaget symbol_tablet &symbol_table; const bool disable_runtime_checks; const size_t max_array_length; + lazy_methodst &lazy_methods; // conversion void convert(const classt &c); @@ -81,7 +84,7 @@ void java_bytecode_convert_classt::convert(const classt &c) debug() << "Skip class " << c.name << " (already loaded)" << eom; return; } - + class_typet class_type; class_type.set_tag(c.name); @@ -135,13 +138,19 @@ void java_bytecode_convert_classt::convert(const classt &c) // now do methods for(const auto &method : c.methods) - java_bytecode_convert_method( - *class_symbol, - method, - symbol_table, - get_message_handler(), - disable_runtime_checks, - max_array_length); + { + const irep_idt method_identifier= + id2string(qualified_classname)+ + "."+id2string(method.name)+ + ":"+method.signature; + java_bytecode_convert_method_lazy( + *class_symbol,method_identifier,method,symbol_table); + lazy_methods[method_identifier]= + std::make_pair(class_symbol,&method); + } + //java_bytecode_convert_method( + // *class_symbol, method, symbol_table, get_message_handler(), + // disable_runtime_checks, max_array_length); // is this a root class? if(c.extends.empty()) @@ -329,13 +338,15 @@ bool java_bytecode_convert_class( symbol_tablet &symbol_table, message_handlert &message_handler, bool disable_runtime_checks, - size_t max_array_length) + size_t max_array_length, + lazy_methodst &lazy_methods) { java_bytecode_convert_classt java_bytecode_convert_class( symbol_table, message_handler, disable_runtime_checks, - max_array_length); + max_array_length, + lazy_methods); try { diff --git a/src/java_bytecode/java_bytecode_convert_class.h b/src/java_bytecode/java_bytecode_convert_class.h index ffaaf6e34da..8c1dccc02f5 100644 --- a/src/java_bytecode/java_bytecode_convert_class.h +++ b/src/java_bytecode/java_bytecode_convert_class.h @@ -14,11 +14,15 @@ Author: Daniel Kroening, kroening@kroening.com #include "java_bytecode_parse_tree.h" +typedef std::map > + lazy_methodst; + bool java_bytecode_convert_class( const java_bytecode_parse_treet &parse_tree, symbol_tablet &symbol_table, message_handlert &message_handler, bool disable_runtime_checks, - size_t max_array_length); + size_t max_array_length, + lazy_methodst &); #endif // CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_CONVERT_CLASS_H diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 54412747708..652547b9def 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -20,6 +20,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include #include #include "java_bytecode_convert_method.h" @@ -181,6 +182,35 @@ const exprt java_bytecode_convert_methodt::variable( } } +void java_bytecode_convert_method_lazy( + const symbolt& class_symbol, + const irep_idt method_identifier, + const java_bytecode_parse_treet::methodt &m, + symbol_tablet& symbol_table) +{ + symbolt method_symbol; + typet member_type=java_type_from_string(m.signature); + + method_symbol.name=method_identifier; + method_symbol.base_name=m.base_name; + method_symbol.mode=ID_java; + method_symbol.location=m.source_location; + method_symbol.location.set_function(method_identifier); + + if(method_symbol.base_name=="") + { + method_symbol.pretty_name=id2string(class_symbol.pretty_name)+"."+ + id2string(class_symbol.base_name)+"()"; + member_type.set(ID_constructor,true); + } + else + method_symbol.pretty_name=id2string(class_symbol.pretty_name)+"."+ + id2string(m.base_name)+"()"; + + method_symbol.type=member_type; + symbol_table.add(method_symbol); +} + /*******************************************************************\ Function: java_bytecode_convert_methodt::convert @@ -347,10 +377,10 @@ void java_bytecode_convert_methodt::convert( if((!m.is_abstract) && (!m.is_native)) method_symbol.value=convert_instructions(m, code_type); - // do we have the method symbol already? + // Replace the existing stub symbol with the real deal: const auto s_it=symbol_table.symbols.find(method.get_name()); - if(s_it!=symbol_table.symbols.end()) - symbol_table.symbols.erase(s_it); // erase, we stubbed it + assert(s_it!=symbol_table.symbols.end()); + symbol_table.symbols.erase(s_it); symbol_table.add(method_symbol); } @@ -1113,12 +1143,25 @@ codet java_bytecode_convert_methodt::convert_instructions( symbol_table.add(symbol); } + needed_methods.push_back(arg0.get(ID_identifier)); + if(is_virtual) { // dynamic binding assert(use_this); assert(!call.arguments().empty()); call.function()=arg0; + const auto& call_class=arg0.get(ID_C_class); + assert(call_class!=irep_idt()); + const auto& call_basename=arg0.get(ID_component_name); + assert(call_basename!=irep_idt()); + auto child_classes=class_hierarchy.get_children_trans(call_class); + for(const auto& child_class : child_classes) + { + auto methodid=id2string(child_class)+"."+id2string(call_basename); + if(symbol_table.has_symbol(methodid)) + needed_methods.push_back(methodid); + } } else { @@ -2144,13 +2187,17 @@ void java_bytecode_convert_method( symbol_tablet &symbol_table, message_handlert &message_handler, bool disable_runtime_checks, - size_t max_array_length) + size_t max_array_length, + std::vector& needed_methods, + const class_hierarchyt& ch) { java_bytecode_convert_methodt java_bytecode_convert_method( symbol_table, message_handler, disable_runtime_checks, - max_array_length); + max_array_length, + needed_methods, + ch); java_bytecode_convert_method(class_symbol, method); } diff --git a/src/java_bytecode/java_bytecode_convert_method.h b/src/java_bytecode/java_bytecode_convert_method.h index 8945af95bd1..327bfd09932 100644 --- a/src/java_bytecode/java_bytecode_convert_method.h +++ b/src/java_bytecode/java_bytecode_convert_method.h @@ -14,12 +14,22 @@ Author: Daniel Kroening, kroening@kroening.com #include "java_bytecode_parse_tree.h" +class class_hierarchyt; + void java_bytecode_convert_method( const symbolt &class_symbol, const java_bytecode_parse_treet::methodt &, symbol_tablet &symbol_table, message_handlert &message_handler, bool disable_runtime_checks, - size_t max_array_length); + size_t max_array_length, + std::vector& needed_methods, + const class_hierarchyt&); + +void java_bytecode_convert_method_lazy( + const symbolt &class_symbol, + const irep_idt method_identifier, + const java_bytecode_parse_treet::methodt &, + symbol_tablet &symbol_table); #endif // CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_CONVERT_METHOD_H diff --git a/src/java_bytecode/java_bytecode_convert_method_class.h b/src/java_bytecode/java_bytecode_convert_method_class.h index 8c0e708a530..30d0d974646 100644 --- a/src/java_bytecode/java_bytecode_convert_method_class.h +++ b/src/java_bytecode/java_bytecode_convert_method_class.h @@ -15,12 +15,14 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include "java_bytecode_parse_tree.h" +#include "java_bytecode_convert_class.h" #include #include class symbol_tablet; class symbolt; +class class_hierarchyt; class java_bytecode_convert_methodt:public messaget { @@ -29,11 +31,15 @@ class java_bytecode_convert_methodt:public messaget symbol_tablet &_symbol_table, message_handlert &_message_handler, bool _disable_runtime_checks, - size_t _max_array_length): + size_t _max_array_length, + std::vector& _needed_methods, + const class_hierarchyt& _ch): messaget(_message_handler), symbol_table(_symbol_table), disable_runtime_checks(_disable_runtime_checks), - max_array_length(_max_array_length) + max_array_length(_max_array_length), + needed_methods(_needed_methods), + class_hierarchy(_ch) { } @@ -52,6 +58,8 @@ class java_bytecode_convert_methodt:public messaget symbol_tablet &symbol_table; const bool disable_runtime_checks; const size_t max_array_length; + std::vector& needed_methods; + const class_hierarchyt& class_hierarchy; irep_idt method_id; irep_idt current_method; diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index 1d9d9f57b41..fb0e19ef487 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -14,8 +14,11 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include + #include "java_bytecode_language.h" #include "java_bytecode_convert_class.h" +#include "java_bytecode_convert_method.h" #include "java_bytecode_internal_additions.h" #include "java_bytecode_typecheck.h" #include "java_entry_point.h" @@ -180,10 +183,15 @@ Function: java_bytecode_languaget::typecheck \*******************************************************************/ + + bool java_bytecode_languaget::typecheck( symbol_tablet &symbol_table, const std::string &module) { + std::map > + lazy_methods; + // first convert all for(java_class_loadert::class_mapt::const_iterator c_it=java_class_loader.class_map.begin(); @@ -200,10 +208,73 @@ bool java_bytecode_languaget::typecheck( symbol_table, get_message_handler(), disable_runtime_checks, - max_user_array_length)) + max_user_array_length, + lazy_methods)) return true; } + // Now incrementally elaborate methods that are reachable from this entry point: + + // Convert-method will need this to find virtual function targets. + class_hierarchyt ch; + ch(symbol_table); + + std::vector worklist1; + std::vector worklist2; + + auto main_function=get_main_symbol(symbol_table,main_class,get_message_handler(),true); + if(main_function.stop_convert) + { + // Failed, mark all functions in the given main class reachable. + const auto& methods=java_class_loader.class_map.at(main_class).parsed_class.methods; + for(const auto& method : methods) + { + const irep_idt methodid="java::"+id2string(main_class)+"."+ + id2string(method.name)+":"+ + id2string(method.signature); + worklist2.push_back(methodid); + } + } + else + worklist2.push_back(main_function.main_function.name); + + std::set already_populated; + while(worklist2.size()!=0) + { + std::swap(worklist1,worklist2); + for(const auto& mname : worklist1) + { + if(!already_populated.insert(mname).second) + continue; + auto findit=lazy_methods.find(mname); + if(findit==lazy_methods.end()) + { + debug() << "Skip " << mname << eom; + continue; + } + debug() << "Lazy methods: elaborate " << mname << eom; + const auto& parsed_method=findit->second; + java_bytecode_convert_method(*parsed_method.first,*parsed_method.second, + symbol_table,get_message_handler(), + disable_runtime_checks,max_user_array_length,worklist2,ch); + } + worklist1.clear(); + } + + // Remove symbols for methods that were declared but never used: + symbol_tablet keep_symbols; + + for(const auto& sym : symbol_table.symbols) + { + if(lazy_methods.count(sym.first) && !already_populated.count(sym.first)) + continue; + keep_symbols.add(sym.second); + } + + debug() << "Lazy methods: removed " << symbol_table.symbols.size() - keep_symbols.symbols.size() << " unreachable methods" << eom; + + symbol_table.swap(keep_symbols); + // now typecheck all if(java_bytecode_typecheck( symbol_table, get_message_handler())) diff --git a/src/java_bytecode/java_entry_point.cpp b/src/java_bytecode/java_entry_point.cpp index dcc3dead0a8..44a59091ba2 100644 --- a/src/java_bytecode/java_entry_point.cpp +++ b/src/java_bytecode/java_entry_point.cpp @@ -327,11 +327,11 @@ void java_record_outputs( } } - main_function_resultt get_main_symbol( symbol_tablet &symbol_table, const irep_idt &main_class, - message_handlert &message_handler) + message_handlert &message_handler, + bool allow_no_body) { symbolt symbol; main_function_resultt res; @@ -415,7 +415,7 @@ main_function_resultt get_main_symbol( } // check if it has a body - if(symbol.value.is_nil()) + if(symbol.value.is_nil() && !allow_no_body) { message.error() << "main method `" << main_class << "' has no body" << messaget::eom; @@ -480,7 +480,7 @@ main_function_resultt get_main_symbol( symbol=symbol_table.symbols.find(*matches.begin())->second; // check if it has a body - if(symbol.value.is_nil()) + if(symbol.value.is_nil() && !allow_no_body) { message.error() << "main method `" << main_class << "' has no body" << messaget::eom; diff --git a/src/java_bytecode/java_entry_point.h b/src/java_bytecode/java_entry_point.h index 7fa562de89a..82071aa26b1 100644 --- a/src/java_bytecode/java_entry_point.h +++ b/src/java_bytecode/java_entry_point.h @@ -28,6 +28,7 @@ typedef struct main_function_resultt get_main_symbol( symbol_tablet &symbol_table, const irep_idt &main_class, - message_handlert &); + message_handlert &, + bool allow_no_body = false); #endif // CPROVER_JAVA_BYTECODE_JAVA_ENTRY_POINT_H From b7a7bfb17a7234d8a35cf2d8e43cba447e0272c7 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 1 Nov 2016 14:19:53 +0000 Subject: [PATCH 023/699] Remove dead global variables When lazy method conversion is in use, they might end up unused. --- src/java_bytecode/java_bytecode_language.cpp | 21 +++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index fb0e19ef487..fc5ee421343 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -171,6 +171,19 @@ bool java_bytecode_languaget::parse( return false; } +static void gather_needed_globals(const exprt& e, const symbol_tablet& symbol_table, symbol_tablet& needed) +{ + if(e.id()==ID_symbol) + { + const auto& sym=symbol_table.lookup(to_symbol_expr(e).get_identifier()); + if(sym.is_static_lifetime) + needed.add(sym); + } + else + forall_operands(opit,e) + gather_needed_globals(*opit,symbol_table,needed); +} + /*******************************************************************\ Function: java_bytecode_languaget::typecheck @@ -183,8 +196,6 @@ Function: java_bytecode_languaget::typecheck \*******************************************************************/ - - bool java_bytecode_languaget::typecheck( symbol_tablet &symbol_table, const std::string &module) @@ -266,12 +277,16 @@ bool java_bytecode_languaget::typecheck( for(const auto& sym : symbol_table.symbols) { + if(sym.second.is_static_lifetime) + continue; if(lazy_methods.count(sym.first) && !already_populated.count(sym.first)) continue; + if(sym.second.type.id()==ID_code) + gather_needed_globals(sym.second.value,symbol_table,keep_symbols); keep_symbols.add(sym.second); } - debug() << "Lazy methods: removed " << symbol_table.symbols.size() - keep_symbols.symbols.size() << " unreachable methods" << eom; + debug() << "Lazy methods: removed " << symbol_table.symbols.size() - keep_symbols.symbols.size() << " unreachable methods and globals" << eom; symbol_table.swap(keep_symbols); From caf804e4721759dca5953ccea6bb118baf88a440 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 2 Nov 2016 17:02:41 +0000 Subject: [PATCH 024/699] Restrict virtual method targets to known-created types Previously even with lazy method conversion enabled, if we had a caller to A.f and C.f overrides A.f, we would generate a possible call to C.f even if a C is never instantiated in any reachable method. This commit changes that, such that we need *both* a callsite and evidence of a C being constructed to generate the callgraph edge. --- .../java_bytecode_convert_method.cpp | 24 ++- .../java_bytecode_convert_method.h | 1 + .../java_bytecode_convert_method_class.h | 3 + src/java_bytecode/java_bytecode_language.cpp | 156 +++++++++++++++--- 4 files changed, 148 insertions(+), 36 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 652547b9def..39d347cdb1c 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -1067,7 +1067,10 @@ codet java_bytecode_convert_methodt::convert_instructions( { if(as_string(arg0.get(ID_identifier)) .find("")!=std::string::npos) + { + needed_classes.insert(classname); code_type.set(ID_constructor, true); + } else code_type.set(ID_java_super_method_call, true); } @@ -1143,30 +1146,19 @@ codet java_bytecode_convert_methodt::convert_instructions( symbol_table.add(symbol); } - needed_methods.push_back(arg0.get(ID_identifier)); - if(is_virtual) { // dynamic binding assert(use_this); assert(!call.arguments().empty()); call.function()=arg0; - const auto& call_class=arg0.get(ID_C_class); - assert(call_class!=irep_idt()); - const auto& call_basename=arg0.get(ID_component_name); - assert(call_basename!=irep_idt()); - auto child_classes=class_hierarchy.get_children_trans(call_class); - for(const auto& child_class : child_classes) - { - auto methodid=id2string(child_class)+"."+id2string(call_basename); - if(symbol_table.has_symbol(methodid)) - needed_methods.push_back(methodid); - } + // Populate needed methods later, once we know what object types can exist. } else { // static binding call.function()=symbol_exprt(arg0.get(ID_identifier), arg0.type()); + needed_methods.push_back(arg0.get(ID_identifier)); } call.function().add_source_location()=loc; @@ -1708,6 +1700,8 @@ codet java_bytecode_convert_methodt::convert_instructions( symbol_exprt symbol_expr(arg0.type()); const auto &field_name=arg0.get_string(ID_component_name); symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+field_name); + if(arg0.type().id()==ID_symbol) + needed_classes.insert(to_symbol_type(arg0.type()).get_identifier()); results[0]=java_bytecode_promotion(symbol_expr); // set $assertionDisabled to false @@ -1725,6 +1719,8 @@ codet java_bytecode_convert_methodt::convert_instructions( symbol_exprt symbol_expr(arg0.type()); const auto &field_name=arg0.get_string(ID_component_name); symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+field_name); + if(arg0.type().id()==ID_symbol) + needed_classes.insert(to_symbol_type(arg0.type()).get_identifier()); c=code_assignt(symbol_expr, op[0]); } else if(statement==patternt("?2?")) // i2c etc. @@ -2189,6 +2185,7 @@ void java_bytecode_convert_method( bool disable_runtime_checks, size_t max_array_length, std::vector& needed_methods, + std::set& needed_classes, const class_hierarchyt& ch) { java_bytecode_convert_methodt java_bytecode_convert_method( @@ -2197,6 +2194,7 @@ void java_bytecode_convert_method( disable_runtime_checks, max_array_length, needed_methods, + needed_classes, ch); java_bytecode_convert_method(class_symbol, method); diff --git a/src/java_bytecode/java_bytecode_convert_method.h b/src/java_bytecode/java_bytecode_convert_method.h index 327bfd09932..b6302161a43 100644 --- a/src/java_bytecode/java_bytecode_convert_method.h +++ b/src/java_bytecode/java_bytecode_convert_method.h @@ -24,6 +24,7 @@ void java_bytecode_convert_method( bool disable_runtime_checks, size_t max_array_length, std::vector& needed_methods, + std::set& needed_classes, const class_hierarchyt&); void java_bytecode_convert_method_lazy( diff --git a/src/java_bytecode/java_bytecode_convert_method_class.h b/src/java_bytecode/java_bytecode_convert_method_class.h index 30d0d974646..8eaf7ac8af5 100644 --- a/src/java_bytecode/java_bytecode_convert_method_class.h +++ b/src/java_bytecode/java_bytecode_convert_method_class.h @@ -33,12 +33,14 @@ class java_bytecode_convert_methodt:public messaget bool _disable_runtime_checks, size_t _max_array_length, std::vector& _needed_methods, + std::set& _needed_classes, const class_hierarchyt& _ch): messaget(_message_handler), symbol_table(_symbol_table), disable_runtime_checks(_disable_runtime_checks), max_array_length(_max_array_length), needed_methods(_needed_methods), + needed_classes(_needed_classes), class_hierarchy(_ch) { } @@ -59,6 +61,7 @@ class java_bytecode_convert_methodt:public messaget const bool disable_runtime_checks; const size_t max_array_length; std::vector& needed_methods; + std::set& needed_classes; const class_hierarchyt& class_hierarchy; irep_idt method_id; diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index fc5ee421343..057859cef04 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -171,6 +171,48 @@ bool java_bytecode_languaget::parse( return false; } +static void get_virtual_method_targets( + const code_function_callt& c, + const std::set& needed_classes, + std::vector& needed_methods, + const symbol_tablet& symbol_table, + const class_hierarchyt& class_hierarchy) +{ + + const auto& called_function=c.function(); + assert(called_function.id()==ID_virtual_function); + + const auto& call_class=called_function.get(ID_C_class); + assert(call_class!=irep_idt()); + const auto& call_basename=called_function.get(ID_component_name); + assert(call_basename!=irep_idt()); + + auto child_classes=class_hierarchy.get_children_trans(call_class); + child_classes.push_back(call_class); + for(const auto& child_class : child_classes) + { + // Program-wide, is this class ever instantiated? + if(!needed_classes.count(child_class)) + continue; + auto methodid=id2string(child_class)+"."+id2string(call_basename); + if(symbol_table.has_symbol(methodid)) + needed_methods.push_back(methodid); + } +} + +static void gather_virtual_callsites(const exprt& e, std::vector& result) +{ + if(e.id()!=ID_code) + return; + const codet& c=to_code(e); + if(c.get_statement()==ID_function_call && + to_code_function_call(c).function().id()==ID_virtual_function) + result.push_back(&to_code_function_call(c)); + else + forall_operands(it,e) + gather_virtual_callsites(*it,result); +} + static void gather_needed_globals(const exprt& e, const symbol_tablet& symbol_table, symbol_tablet& needed) { if(e.id()==ID_symbol) @@ -184,6 +226,48 @@ static void gather_needed_globals(const exprt& e, const symbol_tablet& symbol_ta gather_needed_globals(*opit,symbol_table,needed); } +static void gather_field_types( + const typet& class_type, + const namespacet& ns, + std::set& needed_classes) +{ + const auto& underlying_type=to_struct_type(ns.follow(class_type)); + for(const auto& field : underlying_type.components()) + { + if(field.type().id()==ID_struct || field.type().id()==ID_symbol) + gather_field_types(field.type(),ns,needed_classes); + else if(field.type().id()==ID_pointer) + { + // Skip array primitive pointers, for example: + if(field.type().subtype().id()!=ID_symbol) + continue; + const auto& field_classid=to_symbol_type(field.type().subtype()).get_identifier(); + if(needed_classes.insert(field_classid).second) + gather_field_types(field.type().subtype(),ns,needed_classes); + } + } +} + +static void initialise_needed_classes( + const std::vector& entry_points, + const namespacet& ns, + std::set& needed_classes) +{ + for(const auto& mname : entry_points) + { + const auto& symbol=ns.lookup(mname); + const auto& mtype=to_code_type(symbol.type); + for(const auto& param : mtype.parameters()) + { + if(param.type().id()==ID_pointer) + { + needed_classes.insert(to_symbol_type(param.type().subtype()).get_identifier()); + gather_field_types(param.type().subtype(),ns,needed_classes); + } + } + } +} + /*******************************************************************\ Function: java_bytecode_languaget::typecheck @@ -230,8 +314,8 @@ bool java_bytecode_languaget::typecheck( class_hierarchyt ch; ch(symbol_table); - std::vector worklist1; - std::vector worklist2; + std::vector method_worklist1; + std::vector method_worklist2; auto main_function=get_main_symbol(symbol_table,main_class,get_message_handler(),true); if(main_function.stop_convert) @@ -243,34 +327,60 @@ bool java_bytecode_languaget::typecheck( const irep_idt methodid="java::"+id2string(main_class)+"."+ id2string(method.name)+":"+ id2string(method.signature); - worklist2.push_back(methodid); + method_worklist2.push_back(methodid); } } else - worklist2.push_back(main_function.main_function.name); + method_worklist2.push_back(main_function.main_function.name); - std::set already_populated; - while(worklist2.size()!=0) - { - std::swap(worklist1,worklist2); - for(const auto& mname : worklist1) + std::set needed_classes; + initialise_needed_classes(method_worklist2,namespacet(symbol_table),needed_classes); + + std::set methods_already_populated; + std::vector virtual_callsites; + + bool any_new_methods; + do { + + any_new_methods=false; + while(method_worklist2.size()!=0) { - if(!already_populated.insert(mname).second) - continue; - auto findit=lazy_methods.find(mname); - if(findit==lazy_methods.end()) + std::swap(method_worklist1,method_worklist2); + for(const auto& mname : method_worklist1) { - debug() << "Skip " << mname << eom; - continue; + if(!methods_already_populated.insert(mname).second) + continue; + auto findit=lazy_methods.find(mname); + if(findit==lazy_methods.end()) + { + debug() << "Skip " << mname << eom; + continue; + } + debug() << "Lazy methods: elaborate " << mname << eom; + const auto& parsed_method=findit->second; + java_bytecode_convert_method(*parsed_method.first,*parsed_method.second, + symbol_table,get_message_handler(), + disable_runtime_checks,max_user_array_length, + method_worklist2,needed_classes,ch); + gather_virtual_callsites(symbol_table.lookup(mname).value,virtual_callsites); + any_new_methods=true; } - debug() << "Lazy methods: elaborate " << mname << eom; - const auto& parsed_method=findit->second; - java_bytecode_convert_method(*parsed_method.first,*parsed_method.second, - symbol_table,get_message_handler(), - disable_runtime_checks,max_user_array_length,worklist2,ch); + method_worklist1.clear(); } - worklist1.clear(); - } + + // Given the object types we now know may be created, populate more + // possible virtual function call targets: + + debug() << "Lazy methods: add virtual method targets (" << virtual_callsites.size() << + " callsites)" << eom; + + for(const auto& callsite : virtual_callsites) + { + get_virtual_method_targets(*callsite,needed_classes,method_worklist2, + symbol_table,ch); + } + + } while(any_new_methods); // Remove symbols for methods that were declared but never used: symbol_tablet keep_symbols; @@ -279,7 +389,7 @@ bool java_bytecode_languaget::typecheck( { if(sym.second.is_static_lifetime) continue; - if(lazy_methods.count(sym.first) && !already_populated.count(sym.first)) + if(lazy_methods.count(sym.first) && !methods_already_populated.count(sym.first)) continue; if(sym.second.type.id()==ID_code) gather_needed_globals(sym.second.value,symbol_table,keep_symbols); From 6e1133da85836360375d846c6ee03f05aff64d42 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 21 Nov 2016 15:01:38 +0000 Subject: [PATCH 025/699] Mark all classes in root jar reachable if it doesn't declare a main function --- src/java_bytecode/java_bytecode_language.cpp | 24 ++++++++++++++------ src/java_bytecode/java_bytecode_language.h | 1 + src/java_bytecode/java_class_loader.h | 1 - 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index 057859cef04..dc6c350ba7f 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -150,6 +150,8 @@ bool java_bytecode_languaget::parse( { status() << "JAR file without entry point: loading it all" << eom; java_class_loader.load_entire_jar(path); + for(const auto& kv : java_class_loader.jar_map.at(path).entries) + main_jar_classes.push_back(kv.first); } else java_class_loader.add_jar_file(path); @@ -320,14 +322,22 @@ bool java_bytecode_languaget::typecheck( auto main_function=get_main_symbol(symbol_table,main_class,get_message_handler(),true); if(main_function.stop_convert) { - // Failed, mark all functions in the given main class reachable. - const auto& methods=java_class_loader.class_map.at(main_class).parsed_class.methods; - for(const auto& method : methods) + // Failed, mark all functions in the given main class(es) reachable. + std::vector reachable_classes; + if(!main_class.empty()) + reachable_classes.push_back(main_class); + else + reachable_classes=main_jar_classes; + for(const auto& classname : reachable_classes) { - const irep_idt methodid="java::"+id2string(main_class)+"."+ - id2string(method.name)+":"+ - id2string(method.signature); - method_worklist2.push_back(methodid); + const auto& methods=java_class_loader.class_map.at(classname).parsed_class.methods; + for(const auto& method : methods) + { + const irep_idt methodid="java::"+id2string(classname)+"."+ + id2string(method.name)+":"+ + id2string(method.signature); + method_worklist2.push_back(methodid); + } } } else diff --git a/src/java_bytecode/java_bytecode_language.h b/src/java_bytecode/java_bytecode_language.h index 5937f6f4fd4..36b28682dca 100644 --- a/src/java_bytecode/java_bytecode_language.h +++ b/src/java_bytecode/java_bytecode_language.h @@ -72,6 +72,7 @@ class java_bytecode_languaget:public languaget protected: irep_idt main_class; + std::vector main_jar_classes; java_class_loadert java_class_loader; bool assume_inputs_non_null; // assume inputs variables to be non-null diff --git a/src/java_bytecode/java_class_loader.h b/src/java_bytecode/java_class_loader.h index 4d67b3e7164..b2a4953445a 100644 --- a/src/java_bytecode/java_class_loader.h +++ b/src/java_bytecode/java_class_loader.h @@ -37,7 +37,6 @@ class java_class_loadert:public messaget jar_poolt jar_pool; -protected: class jar_map_entryt { public: From 49bfea4d8b0fb6b8b10e1a1abf09e565a7daa210 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 23 Nov 2016 11:02:34 +0000 Subject: [PATCH 026/699] Add this-parameter before determining needed classes If the given entry point has a this-parameter of type A, that constitutes evidence that virtual callsites might target a class of type A. --- .../java_bytecode_convert_method.cpp | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 39d347cdb1c..d10cfdec60b 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -207,6 +207,18 @@ void java_bytecode_convert_method_lazy( method_symbol.pretty_name=id2string(class_symbol.pretty_name)+"."+ id2string(m.base_name)+"()"; + // do we need to add 'this' as a parameter? + if(!m.is_static) + { + code_typet &code_type=to_code_type(member_type); + code_typet::parameterst ¶meters=code_type.parameters(); + code_typet::parametert this_p; + const reference_typet object_ref_type(symbol_typet(class_symbol.name)); + this_p.type()=object_ref_type; + this_p.set_this(); + parameters.insert(parameters.begin(), this_p); + } + method_symbol.type=member_type; symbol_table.add(method_symbol); } @@ -227,29 +239,17 @@ void java_bytecode_convert_methodt::convert( const symbolt &class_symbol, const methodt &m) { - typet member_type=java_type_from_string(m.signature); - - assert(member_type.id()==ID_code); - const irep_idt method_identifier= id2string(class_symbol.name)+"."+id2string(m.name)+":"+m.signature; method_id=method_identifier; + const auto& old_sym=symbol_table.lookup(method_identifier); + + typet member_type=old_sym.type; code_typet &code_type=to_code_type(member_type); method_return_type=code_type.return_type(); code_typet::parameterst ¶meters=code_type.parameters(); - // do we need to add 'this' as a parameter? - if(!m.is_static) - { - code_typet::parametert this_p; - const reference_typet object_ref_type( - symbol_typet(class_symbol.name)); - this_p.type()=object_ref_type; - this_p.set_this(); - parameters.insert(parameters.begin(), this_p); - } - variables.clear(); // find parameter names in the local variable table: From e12448b0dfde0b0b37f5f329d451fcabd5f8d431 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 30 Nov 2016 15:38:08 +0000 Subject: [PATCH 027/699] Lazy method conversion: load callee parent classes Previously lazy virtual callsite resolution would assume that in order to call B.f, it is necessary to instantiate a B and call A.f, where A is some parent of B. This commit amends that to allow creation of a C, where C is a subtype of B and does not override f itself, is enough for B.f to be callable. --- src/java_bytecode/java_bytecode_language.cpp | 84 +++++++++++++++++--- 1 file changed, 72 insertions(+), 12 deletions(-) diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index dc6c350ba7f..8e5ce448b57 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -173,14 +173,29 @@ bool java_bytecode_languaget::parse( return false; } +static irep_idt get_virtual_method_target( + const std::set& needed_classes, + const irep_idt& call_basename, + const irep_idt& classname, + const symbol_tablet& symbol_table) +{ + // Program-wide, is this class ever instantiated? + if(!needed_classes.count(classname)) + return irep_idt(); + auto methodid=id2string(classname)+"."+id2string(call_basename); + if(symbol_table.has_symbol(methodid)) + return methodid; + else + return irep_idt(); +} + static void get_virtual_method_targets( const code_function_callt& c, const std::set& needed_classes, std::vector& needed_methods, - const symbol_tablet& symbol_table, + symbol_tablet& symbol_table, const class_hierarchyt& class_hierarchy) { - const auto& called_function=c.function(); assert(called_function.id()==ID_virtual_function); @@ -189,17 +204,56 @@ static void get_virtual_method_targets( const auto& call_basename=called_function.get(ID_component_name); assert(call_basename!=irep_idt()); + auto old_size=needed_methods.size(); + auto child_classes=class_hierarchy.get_children_trans(call_class); - child_classes.push_back(call_class); for(const auto& child_class : child_classes) { - // Program-wide, is this class ever instantiated? - if(!needed_classes.count(child_class)) - continue; - auto methodid=id2string(child_class)+"."+id2string(call_basename); - if(symbol_table.has_symbol(methodid)) - needed_methods.push_back(methodid); + auto child_method=get_virtual_method_target(needed_classes,call_basename, + child_class,symbol_table); + if(child_method!=irep_idt()) + needed_methods.push_back(child_method); + } + + irep_idt parent_class_id=call_class; + while(1) + { + auto parent_method=get_virtual_method_target(needed_classes,call_basename, + parent_class_id,symbol_table); + if(parent_method!=irep_idt()) + { + needed_methods.push_back(parent_method); + break; + } + else + { + auto findit=class_hierarchy.class_map.find(parent_class_id); + if(findit==class_hierarchy.class_map.end()) + break; + else + { + const auto& entry=findit->second; + if(entry.parents.size()==0) + break; + else + parent_class_id=entry.parents[0]; + } + } } + + if(needed_methods.size()==old_size) + { + // Didn't find any candidate callee. Generate a stub. + std::string stubname=id2string(call_class)+"."+id2string(call_basename); + symbolt symbol; + symbol.name=stubname; + symbol.base_name=call_basename; + symbol.type=c.function().type(); + symbol.value.make_nil(); + symbol.mode=ID_java; + symbol_table.add(symbol); + } + } static void gather_virtual_callsites(const exprt& e, std::vector& result) @@ -253,6 +307,7 @@ static void gather_field_types( static void initialise_needed_classes( const std::vector& entry_points, const namespacet& ns, + const class_hierarchyt& ch, std::set& needed_classes) { for(const auto& mname : entry_points) @@ -263,8 +318,12 @@ static void initialise_needed_classes( { if(param.type().id()==ID_pointer) { - needed_classes.insert(to_symbol_type(param.type().subtype()).get_identifier()); - gather_field_types(param.type().subtype(),ns,needed_classes); + const auto& param_classid=to_symbol_type(param.type().subtype()).get_identifier(); + std::vector class_and_parents=ch.get_parents_trans(param_classid); + class_and_parents.push_back(param_classid); + for(const auto& classid : class_and_parents) + needed_classes.insert(classid); + gather_field_types(param.type().subtype(),ns,needed_classes); } } } @@ -344,7 +403,7 @@ bool java_bytecode_languaget::typecheck( method_worklist2.push_back(main_function.main_function.name); std::set needed_classes; - initialise_needed_classes(method_worklist2,namespacet(symbol_table),needed_classes); + initialise_needed_classes(method_worklist2,namespacet(symbol_table),ch,needed_classes); std::set methods_already_populated; std::vector virtual_callsites; @@ -386,6 +445,7 @@ bool java_bytecode_languaget::typecheck( for(const auto& callsite : virtual_callsites) { + // This will also create a stub if a virtual callsite has no targets. get_virtual_method_targets(*callsite,needed_classes,method_worklist2, symbol_table,ch); } From d20bdc644adc98c740d0c264cac43347f6af429e Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 17 Jan 2017 11:55:35 +0000 Subject: [PATCH 028/699] Always assume String, Class and Object are callable --- src/java_bytecode/java_bytecode_language.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index 8e5ce448b57..1655347f627 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -327,6 +327,13 @@ static void initialise_needed_classes( } } } + + // Also add classes whose instances are magically + // created by the JVM and so won't be spotted by + // looking for constructors and calls as usual: + needed_classes.insert("java::java.lang.String"); + needed_classes.insert("java::java.lang.Class"); + needed_classes.insert("java::java.lang.Object"); } /*******************************************************************\ From 93af0389f44de0ccca8c74e55b4a814073b36794 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 17 Jan 2017 12:01:49 +0000 Subject: [PATCH 029/699] Don't try to call an abstract function --- src/goto-programs/remove_virtual_functions.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/goto-programs/remove_virtual_functions.cpp b/src/goto-programs/remove_virtual_functions.cpp index 4b950593aed..c93b50a2500 100644 --- a/src/goto-programs/remove_virtual_functions.cpp +++ b/src/goto-programs/remove_virtual_functions.cpp @@ -339,7 +339,8 @@ void remove_virtual_functionst::get_functions( component_name, functions); - functions.push_back(root_function); + if(root_function.symbol_expr!=symbol_exprt()) + functions.push_back(root_function); } /*******************************************************************\ From 21decbb64ea03022d3986d60e638c6165f40890e Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 25 Jan 2017 15:53:40 +0000 Subject: [PATCH 030/699] Make lazy method loading optional --- .../java_bytecode_convert_class.cpp | 42 +++++++--- .../java_bytecode_convert_class.h | 7 +- .../java_bytecode_convert_method.cpp | 23 +++--- .../java_bytecode_convert_method.h | 25 +++++- .../java_bytecode_convert_method_class.h | 14 ++-- src/java_bytecode/java_bytecode_language.cpp | 76 ++++++++++++++----- src/java_bytecode/java_bytecode_language.h | 17 +++++ src/util/language.h | 9 +++ src/util/language_file.cpp | 16 ++++ src/util/language_file.h | 23 ++++++ 10 files changed, 196 insertions(+), 56 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_class.cpp b/src/java_bytecode/java_bytecode_convert_class.cpp index 2036bcd9bce..eb642baa846 100644 --- a/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/src/java_bytecode/java_bytecode_convert_class.cpp @@ -14,6 +14,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "java_root_class.h" #include "java_types.h" #include "java_bytecode_convert_method.h" +#include "java_bytecode_language.h" #include #include @@ -28,12 +29,14 @@ class java_bytecode_convert_classt:public messaget message_handlert &_message_handler, bool _disable_runtime_checks, size_t _max_array_length, - lazy_methodst& _lm): + lazy_methodst& _lm, + lazy_methods_modet _lazy_methods_mode): messaget(_message_handler), symbol_table(_symbol_table), disable_runtime_checks(_disable_runtime_checks), max_array_length(_max_array_length), - lazy_methods(_lm) + lazy_methods(_lm), + lazy_methods_mode(_lazy_methods_mode) { } @@ -55,6 +58,7 @@ class java_bytecode_convert_classt:public messaget const bool disable_runtime_checks; const size_t max_array_length; lazy_methodst &lazy_methods; + lazy_methods_modet lazy_methods_mode; // conversion void convert(const classt &c); @@ -143,14 +147,30 @@ void java_bytecode_convert_classt::convert(const classt &c) id2string(qualified_classname)+ "."+id2string(method.name)+ ":"+method.signature; + // Always run the lazy pre-stage, as it symbol-table + // registers the function. java_bytecode_convert_method_lazy( - *class_symbol,method_identifier,method,symbol_table); - lazy_methods[method_identifier]= - std::make_pair(class_symbol,&method); + *class_symbol, + method_identifier, + method, + symbol_table); + if(lazy_methods_mode==LAZY_METHODS_MODE_EAGER) + { + // Upgrade to a fully-realized symbol now: + java_bytecode_convert_method( + *class_symbol, + method, + symbol_table, + get_message_handler(), + disable_runtime_checks, + max_array_length); + } + else + { + // Wait for our caller to decide what needs elaborating. + lazy_methods[method_identifier]=std::make_pair(class_symbol, &method); + } } - //java_bytecode_convert_method( - // *class_symbol, method, symbol_table, get_message_handler(), - // disable_runtime_checks, max_array_length); // is this a root class? if(c.extends.empty()) @@ -339,14 +359,16 @@ bool java_bytecode_convert_class( message_handlert &message_handler, bool disable_runtime_checks, size_t max_array_length, - lazy_methodst &lazy_methods) + lazy_methodst &lazy_methods, + lazy_methods_modet lazy_methods_mode) { java_bytecode_convert_classt java_bytecode_convert_class( symbol_table, message_handler, disable_runtime_checks, max_array_length, - lazy_methods); + lazy_methods, + lazy_methods_mode); try { diff --git a/src/java_bytecode/java_bytecode_convert_class.h b/src/java_bytecode/java_bytecode_convert_class.h index 8c1dccc02f5..5cc1526a125 100644 --- a/src/java_bytecode/java_bytecode_convert_class.h +++ b/src/java_bytecode/java_bytecode_convert_class.h @@ -13,9 +13,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include "java_bytecode_parse_tree.h" - -typedef std::map > - lazy_methodst; +#include "java_bytecode_language.h" bool java_bytecode_convert_class( const java_bytecode_parse_treet &parse_tree, @@ -23,6 +21,7 @@ bool java_bytecode_convert_class( message_handlert &message_handler, bool disable_runtime_checks, size_t max_array_length, - lazy_methodst &); + lazy_methodst &, + lazy_methods_modet); #endif // CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_CONVERT_CLASS_H diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index d10cfdec60b..6565e91f72e 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -20,7 +20,6 @@ Author: Daniel Kroening, kroening@kroening.com #include #include -#include #include #include "java_bytecode_convert_method.h" @@ -1068,7 +1067,8 @@ codet java_bytecode_convert_methodt::convert_instructions( if(as_string(arg0.get(ID_identifier)) .find("")!=std::string::npos) { - needed_classes.insert(classname); + if(needed_classes) + needed_classes->insert(classname); code_type.set(ID_constructor, true); } else @@ -1158,7 +1158,8 @@ codet java_bytecode_convert_methodt::convert_instructions( { // static binding call.function()=symbol_exprt(arg0.get(ID_identifier), arg0.type()); - needed_methods.push_back(arg0.get(ID_identifier)); + if(needed_methods) + needed_methods->push_back(arg0.get(ID_identifier)); } call.function().add_source_location()=loc; @@ -1700,8 +1701,8 @@ codet java_bytecode_convert_methodt::convert_instructions( symbol_exprt symbol_expr(arg0.type()); const auto &field_name=arg0.get_string(ID_component_name); symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+field_name); - if(arg0.type().id()==ID_symbol) - needed_classes.insert(to_symbol_type(arg0.type()).get_identifier()); + if(needed_classes && arg0.type().id()==ID_symbol) + needed_classes->insert(to_symbol_type(arg0.type()).get_identifier()); results[0]=java_bytecode_promotion(symbol_expr); // set $assertionDisabled to false @@ -1719,8 +1720,8 @@ codet java_bytecode_convert_methodt::convert_instructions( symbol_exprt symbol_expr(arg0.type()); const auto &field_name=arg0.get_string(ID_component_name); symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+field_name); - if(arg0.type().id()==ID_symbol) - needed_classes.insert(to_symbol_type(arg0.type()).get_identifier()); + if(needed_classes && arg0.type().id()==ID_symbol) + needed_classes->insert(to_symbol_type(arg0.type()).get_identifier()); c=code_assignt(symbol_expr, op[0]); } else if(statement==patternt("?2?")) // i2c etc. @@ -2184,9 +2185,8 @@ void java_bytecode_convert_method( message_handlert &message_handler, bool disable_runtime_checks, size_t max_array_length, - std::vector& needed_methods, - std::set& needed_classes, - const class_hierarchyt& ch) + std::vector *needed_methods, + std::set *needed_classes) { java_bytecode_convert_methodt java_bytecode_convert_method( symbol_table, @@ -2194,8 +2194,7 @@ void java_bytecode_convert_method( disable_runtime_checks, max_array_length, needed_methods, - needed_classes, - ch); + needed_classes); java_bytecode_convert_method(class_symbol, method); } diff --git a/src/java_bytecode/java_bytecode_convert_method.h b/src/java_bytecode/java_bytecode_convert_method.h index b6302161a43..145c7a5cc91 100644 --- a/src/java_bytecode/java_bytecode_convert_method.h +++ b/src/java_bytecode/java_bytecode_convert_method.h @@ -23,9 +23,28 @@ void java_bytecode_convert_method( message_handlert &message_handler, bool disable_runtime_checks, size_t max_array_length, - std::vector& needed_methods, - std::set& needed_classes, - const class_hierarchyt&); + std::vector *needed_methods, + std::set *needed_classes); + +// Must provide both the optional parameters or neither. +inline void java_bytecode_convert_method( + const symbolt &class_symbol, + const java_bytecode_parse_treet::methodt &method, + symbol_tablet &symbol_table, + message_handlert &message_handler, + bool disable_runtime_checks, + size_t max_array_length) +{ + java_bytecode_convert_method( + class_symbol, + method, + symbol_table, + message_handler, + disable_runtime_checks, + max_array_length, + nullptr, + nullptr); +} void java_bytecode_convert_method_lazy( const symbolt &class_symbol, diff --git a/src/java_bytecode/java_bytecode_convert_method_class.h b/src/java_bytecode/java_bytecode_convert_method_class.h index 8eaf7ac8af5..96e640ecdf3 100644 --- a/src/java_bytecode/java_bytecode_convert_method_class.h +++ b/src/java_bytecode/java_bytecode_convert_method_class.h @@ -22,7 +22,6 @@ Author: Daniel Kroening, kroening@kroening.com class symbol_tablet; class symbolt; -class class_hierarchyt; class java_bytecode_convert_methodt:public messaget { @@ -32,16 +31,14 @@ class java_bytecode_convert_methodt:public messaget message_handlert &_message_handler, bool _disable_runtime_checks, size_t _max_array_length, - std::vector& _needed_methods, - std::set& _needed_classes, - const class_hierarchyt& _ch): + std::vector *_needed_methods, + std::set *_needed_classes): messaget(_message_handler), symbol_table(_symbol_table), disable_runtime_checks(_disable_runtime_checks), max_array_length(_max_array_length), needed_methods(_needed_methods), - needed_classes(_needed_classes), - class_hierarchy(_ch) + needed_classes(_needed_classes) { } @@ -60,9 +57,8 @@ class java_bytecode_convert_methodt:public messaget symbol_tablet &symbol_table; const bool disable_runtime_checks; const size_t max_array_length; - std::vector& needed_methods; - std::set& needed_classes; - const class_hierarchyt& class_hierarchy; + std::vector *needed_methods; + std::set *needed_classes; irep_idt method_id; irep_idt current_method; diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index 1655347f627..42c6d0bb9ef 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -48,6 +48,12 @@ void java_bytecode_languaget::get_language_options(const cmdlinet &cmd) std::stoi(cmd.get_value("java-max-input-array-length")); if(cmd.isset("java-max-vla-length")) max_user_array_length=std::stoi(cmd.get_value("java-max-vla-length")); + if(cmd.isset("lazy-methods-context-sensitive")) + lazy_methods_mode=LAZY_METHODS_MODE_CONTEXT_SENSITIVE; + else if(cmd.isset("lazy-methods")) + lazy_methods_mode=LAZY_METHODS_MODE_CONTEXT_INSENSITIVE; + else + lazy_methods_mode=LAZY_METHODS_MODE_EAGER; } /*******************************************************************\ @@ -352,9 +358,6 @@ bool java_bytecode_languaget::typecheck( symbol_tablet &symbol_table, const std::string &module) { - std::map > - lazy_methods; - // first convert all for(java_class_loadert::class_mapt::const_iterator c_it=java_class_loader.class_map.begin(); @@ -372,13 +375,30 @@ bool java_bytecode_languaget::typecheck( get_message_handler(), disable_runtime_checks, max_user_array_length, - lazy_methods)) + lazy_methods, + lazy_methods_mode)) return true; } - // Now incrementally elaborate methods that are reachable from this entry point: + // Now incrementally elaborate methods that are reachable from this entry point. + if(lazy_methods_mode==LAZY_METHODS_MODE_CONTEXT_INSENSITIVE) + { + if(do_ci_lazy_method_conversion(symbol_table, lazy_methods)) + return true; + } + + // now typecheck all + if(java_bytecode_typecheck( + symbol_table, get_message_handler())) + return true; + + return false; +} - // Convert-method will need this to find virtual function targets. +bool java_bytecode_languaget::do_ci_lazy_method_conversion( + symbol_tablet &symbol_table, + lazy_methodst &lazy_methods) +{ class_hierarchyt ch; ch(symbol_table); @@ -432,12 +452,17 @@ bool java_bytecode_languaget::typecheck( debug() << "Skip " << mname << eom; continue; } - debug() << "Lazy methods: elaborate " << mname << eom; + debug() << "CI lazy methods: elaborate " << mname << eom; const auto& parsed_method=findit->second; - java_bytecode_convert_method(*parsed_method.first,*parsed_method.second, - symbol_table,get_message_handler(), - disable_runtime_checks,max_user_array_length, - method_worklist2,needed_classes,ch); + java_bytecode_convert_method( + *parsed_method.first, + *parsed_method.second, + symbol_table, + get_message_handler(), + disable_runtime_checks, + max_user_array_length, + &method_worklist2, + &needed_classes); gather_virtual_callsites(symbol_table.lookup(mname).value,virtual_callsites); any_new_methods=true; } @@ -447,7 +472,7 @@ bool java_bytecode_languaget::typecheck( // Given the object types we now know may be created, populate more // possible virtual function call targets: - debug() << "Lazy methods: add virtual method targets (" << virtual_callsites.size() << + debug() << "CI lazy methods: add virtual method targets (" << virtual_callsites.size() << " callsites)" << eom; for(const auto& callsite : virtual_callsites) @@ -473,18 +498,33 @@ bool java_bytecode_languaget::typecheck( keep_symbols.add(sym.second); } - debug() << "Lazy methods: removed " << symbol_table.symbols.size() - keep_symbols.symbols.size() << " unreachable methods and globals" << eom; + debug() << "CI lazy methods: removed " << symbol_table.symbols.size() - keep_symbols.symbols.size() << " unreachable methods and globals" << eom; symbol_table.swap(keep_symbols); - // now typecheck all - if(java_bytecode_typecheck( - symbol_table, get_message_handler())) - return true; - return false; } +void java_bytecode_languaget::lazy_methods_provided(std::set &methods) const +{ + for(const auto &kv : lazy_methods) + methods.insert(kv.first); +} + +void java_bytecode_languaget::convert_lazy_method( + const irep_idt &id, + symbol_tablet &symtab) +{ + const auto &lazy_method_entry=lazy_methods.at(id); + java_bytecode_convert_method( + *lazy_method_entry.first, + *lazy_method_entry.second, + symtab, + get_message_handler(), + disable_runtime_checks, + max_user_array_length); +} + /*******************************************************************\ Function: java_bytecode_languaget::final diff --git a/src/java_bytecode/java_bytecode_language.h b/src/java_bytecode/java_bytecode_language.h index 36b28682dca..750b92aa367 100644 --- a/src/java_bytecode/java_bytecode_language.h +++ b/src/java_bytecode/java_bytecode_language.h @@ -16,6 +16,16 @@ Author: Daniel Kroening, kroening@kroening.com #define MAX_NONDET_ARRAY_LENGTH_DEFAULT 5 +enum lazy_methods_modet +{ + LAZY_METHODS_MODE_EAGER, + LAZY_METHODS_MODE_CONTEXT_INSENSITIVE, + LAZY_METHODS_MODE_CONTEXT_SENSITIVE +}; + +typedef std::map > + lazy_methodst; + class java_bytecode_languaget:public languaget { public: @@ -69,8 +79,13 @@ class java_bytecode_languaget:public languaget std::set extensions() const override; void modules_provided(std::set &modules) override; + virtual void lazy_methods_provided(std::set &) const override; + virtual void convert_lazy_method( + const irep_idt &id, symbol_tablet &) override; protected: + bool do_ci_lazy_method_conversion(symbol_tablet &, lazy_methodst &); + irep_idt main_class; std::vector main_jar_classes; java_class_loadert java_class_loader; @@ -83,6 +98,8 @@ class java_bytecode_languaget:public languaget // - array size for newarray size_t max_nondet_array_length; // maximal length for non-det array creation size_t max_user_array_length; // max size for user code created arrays + lazy_methodst lazy_methods; + lazy_methods_modet lazy_methods_mode; }; languaget *new_java_bytecode_language(); diff --git a/src/util/language.h b/src/util/language.h index edd83471cd5..b19615496ec 100644 --- a/src/util/language.h +++ b/src/util/language.h @@ -49,6 +49,15 @@ class languaget:public messaget virtual void modules_provided(std::set &modules) { } + // add lazy functions provided to set + + virtual void lazy_methods_provided(std::set &methods) const + { } + + // populate a lazy method + virtual void convert_lazy_method(const irep_idt &id, symbol_tablet &) + { } + // final adjustments, e.g., initialization and call to main() virtual bool final( diff --git a/src/util/language_file.cpp b/src/util/language_file.cpp index dffad975c45..5ecbf9b7438 100644 --- a/src/util/language_file.cpp +++ b/src/util/language_file.cpp @@ -65,6 +65,13 @@ void language_filet::get_modules() language->modules_provided(modules); } +void language_filet::convert_lazy_method( + const irep_idt &id, + symbol_tablet &symtab) +{ + language->convert_lazy_method(id, symtab); +} + /*******************************************************************\ Function: language_filest::show_parse @@ -190,8 +197,17 @@ bool language_filest::typecheck(symbol_tablet &symbol_table) it!=filemap.end(); it++) { if(it->second.modules.empty()) + { if(it->second.language->typecheck(symbol_table, "")) return true; + // register lazy methods. + // TODO: learn about modules and generalise this + // to module-providing languages if required. + std::set lazy_method_ids; + it->second.language->lazy_methods_provided(lazy_method_ids); + for(const auto &id : lazy_method_ids) + lazymethodmap[id]=&it->second; + } } // typecheck modules diff --git a/src/util/language_file.h b/src/util/language_file.h index 533e8d5240e..b538c24e84f 100644 --- a/src/util/language_file.h +++ b/src/util/language_file.h @@ -42,6 +42,10 @@ class language_filet void get_modules(); + void convert_lazy_method( + const irep_idt &id, + symbol_tablet &symtab); + language_filet(const language_filet &rhs); language_filet():language(NULL) @@ -57,9 +61,15 @@ class language_filest:public messaget typedef std::map filemapt; filemapt filemap; + // Contains pointers into filemapt! typedef std::map modulemapt; modulemapt modulemap; + // Contains pointers into filemapt! + // This is safe-ish as long as this is std::map. + typedef std::map lazymethodmapt; + lazymethodmapt lazymethodmap; + void clear_files() { filemap.clear(); @@ -75,10 +85,23 @@ class language_filest:public messaget bool interfaces(symbol_tablet &symbol_table); + bool has_lazy_method(const irep_idt &id) + { + return lazymethodmap.count(id); + } + + void convert_lazy_method( + const irep_idt &id, + symbol_tablet &symtab) + { + return lazymethodmap.at(id)->convert_lazy_method(id, symtab); + } + void clear() { filemap.clear(); modulemap.clear(); + lazymethodmap.clear(); } protected: From 2f47cba7332a8cc9e7a4eec50ff71b3134b93ea2 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 6 Feb 2017 11:18:04 +0000 Subject: [PATCH 031/699] Add CBMC lazy-methods parameter TODO: move all Java frontend parameters into something defined on java_bytecode_languaget and have all driver programs gather the frontends' defined parameters. --- src/cbmc/cbmc_parse_options.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cbmc/cbmc_parse_options.h b/src/cbmc/cbmc_parse_options.h index 87e9beb45d2..adc6e2ee517 100644 --- a/src/cbmc/cbmc_parse_options.h +++ b/src/cbmc/cbmc_parse_options.h @@ -56,6 +56,7 @@ class optionst; "(graphml-witness):" \ "(java-max-vla-length):(java-unwind-enum-static)" \ "(localize-faults)(localize-faults-method):" \ + "(lazy-methods)" \ "(fixedbv)(floatbv)(all-claims)(all-properties)" // legacy, and will eventually disappear // NOLINT(whitespace/line_length) class cbmc_parse_optionst: From 311806ecbf6b27ece359e76f8e312410dd2205d5 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 9 Feb 2017 16:44:27 +0000 Subject: [PATCH 032/699] Document lazy methods --- .../java_bytecode_convert_method.cpp | 19 ++++ src/java_bytecode/java_bytecode_language.cpp | 103 ++++++++++++++++++ 2 files changed, 122 insertions(+) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 6565e91f72e..1cd371c1901 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -181,6 +181,25 @@ const exprt java_bytecode_convert_methodt::variable( } } +/*******************************************************************\ + +Function: java_bytecode_convert_method_lazy + + Inputs: `class_symbol`: class this method belongs to + `method_identifier`: fully qualified method name, including + type signature (e.g. "x.y.z.f:(I)") + `m`: parsed method object to convert + `symbol_table`: global symbol table (will be modified) + + Outputs: + + Purpose: This creates a method symbol in the symtab, but doesn't + actually perform method conversion just yet. The caller + should call java_bytecode_convert_method later to give the + symbol/method a body. + +\*******************************************************************/ + void java_bytecode_convert_method_lazy( const symbolt& class_symbol, const irep_idt method_identifier, diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index 42c6d0bb9ef..310a5ef69dd 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -179,6 +179,27 @@ bool java_bytecode_languaget::parse( return false; } +/*******************************************************************\ + +Function: get_virtual_method_target + + Inputs: `needed_classes`: set of classes that can be instantiated. + Any potential callee not in this set will be ignored. + `call_basename`: unqualified function name with type + signature (e.g. "f:(I)") + `classname`: class name that may define or override a + function named `call_basename`. + `symbol_table`: global symtab + + Outputs: Returns the fully qualified name of `classname`'s definition + of `call_basename` if found and `classname` is present in + `needed_classes`, or irep_idt() otherwise. + + Purpose: Find a virtual callee, if one is defined and the callee type + is known to exist. + +\*******************************************************************/ + static irep_idt get_virtual_method_target( const std::set& needed_classes, const irep_idt& call_basename, @@ -195,6 +216,27 @@ static irep_idt get_virtual_method_target( return irep_idt(); } +/*******************************************************************\ + +Function: get_virtual_method_target + + Inputs: `c`: function call whose potential target functions should + be determined. + `needed_classes`: set of classes that can be instantiated. + Any potential callee not in this set will be ignored. + `symbol_table`: global symtab + `class_hierarchy`: global class hierarchy + + Outputs: Populates `needed_methods` with all possible `c` callees, + taking `needed_classes` into account (virtual function + overrides defined on classes that are not 'needed' are + ignored) + + Purpose: Find possible callees, excluding types that are not known + to be instantiated. + +\*******************************************************************/ + static void get_virtual_method_targets( const code_function_callt& c, const std::set& needed_classes, @@ -262,6 +304,19 @@ static void get_virtual_method_targets( } +/*******************************************************************\ + +Function: gather_virtual_callsites + + Inputs: `e`: expression tree to search + + Outputs: Populates `result` with pointers to each function call + within e that calls a virtual function. + + Purpose: See output + +\*******************************************************************/ + static void gather_virtual_callsites(const exprt& e, std::vector& result) { if(e.id()!=ID_code) @@ -275,6 +330,20 @@ static void gather_virtual_callsites(const exprt& e, std::vector& entry_points, const namespacet& ns, From 49105209d4d7284b7c0094f0ca6aa34e05f17a02 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 9 Feb 2017 16:55:15 +0000 Subject: [PATCH 033/699] Style fixes --- .../java_bytecode_convert_method.cpp | 5 +- src/java_bytecode/java_bytecode_language.cpp | 98 ++++++++++++------- src/java_bytecode/java_bytecode_language.h | 6 +- 3 files changed, 73 insertions(+), 36 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 1cd371c1901..79db9de0f03 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -219,7 +219,7 @@ void java_bytecode_convert_method_lazy( { method_symbol.pretty_name=id2string(class_symbol.pretty_name)+"."+ id2string(class_symbol.base_name)+"()"; - member_type.set(ID_constructor,true); + member_type.set(ID_constructor, true); } else method_symbol.pretty_name=id2string(class_symbol.pretty_name)+"."+ @@ -1171,7 +1171,8 @@ codet java_bytecode_convert_methodt::convert_instructions( assert(use_this); assert(!call.arguments().empty()); call.function()=arg0; - // Populate needed methods later, once we know what object types can exist. + // Populate needed methods later, + // once we know what object types can exist. } else { diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index 310a5ef69dd..c9f1b1771d2 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -257,8 +257,12 @@ static void get_virtual_method_targets( auto child_classes=class_hierarchy.get_children_trans(call_class); for(const auto& child_class : child_classes) { - auto child_method=get_virtual_method_target(needed_classes,call_basename, - child_class,symbol_table); + auto child_method= + get_virtual_method_target( + needed_classes, + call_basename, + child_class, + symbol_table); if(child_method!=irep_idt()) needed_methods.push_back(child_method); } @@ -266,8 +270,12 @@ static void get_virtual_method_targets( irep_idt parent_class_id=call_class; while(1) { - auto parent_method=get_virtual_method_target(needed_classes,call_basename, - parent_class_id,symbol_table); + auto parent_method= + get_virtual_method_target( + needed_classes, + call_basename, + parent_class_id, + symbol_table); if(parent_method!=irep_idt()) { needed_methods.push_back(parent_method); @@ -301,7 +309,6 @@ static void get_virtual_method_targets( symbol.mode=ID_java; symbol_table.add(symbol); } - } /*******************************************************************\ @@ -317,7 +324,9 @@ Function: gather_virtual_callsites \*******************************************************************/ -static void gather_virtual_callsites(const exprt& e, std::vector& result) +static void gather_virtual_callsites( + const exprt& e, + std::vector& result) { if(e.id()!=ID_code) return; @@ -326,8 +335,8 @@ static void gather_virtual_callsites(const exprt& e, std::vector class_and_parents=ch.get_parents_trans(param_classid); + const auto& param_classid= + to_symbol_type(param.type().subtype()).get_identifier(); + std::vector class_and_parents= + ch.get_parents_trans(param_classid); class_and_parents.push_back(param_classid); for(const auto& classid : class_and_parents) needed_classes.insert(classid); - gather_field_types(param.type().subtype(),ns,needed_classes); + gather_field_types(param.type().subtype(), ns, needed_classes); } } } @@ -483,7 +498,8 @@ bool java_bytecode_languaget::typecheck( return true; } - // Now incrementally elaborate methods that are reachable from this entry point. + // Now incrementally elaborate methods + // that are reachable from this entry point. if(lazy_methods_mode==LAZY_METHODS_MODE_CONTEXT_INSENSITIVE) { if(do_ci_lazy_method_conversion(symbol_table, lazy_methods)) @@ -508,7 +524,8 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion( std::vector method_worklist1; std::vector method_worklist2; - auto main_function=get_main_symbol(symbol_table,main_class,get_message_handler(),true); + auto main_function= + get_main_symbol(symbol_table, main_class, get_message_handler(), true); if(main_function.stop_convert) { // Failed, mark all functions in the given main class(es) reachable. @@ -519,7 +536,8 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion( reachable_classes=main_jar_classes; for(const auto& classname : reachable_classes) { - const auto& methods=java_class_loader.class_map.at(classname).parsed_class.methods; + const auto& methods= + java_class_loader.class_map.at(classname).parsed_class.methods; for(const auto& method : methods) { const irep_idt methodid="java::"+id2string(classname)+"."+ @@ -533,18 +551,22 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion( method_worklist2.push_back(main_function.main_function.name); std::set needed_classes; - initialise_needed_classes(method_worklist2,namespacet(symbol_table),ch,needed_classes); + initialise_needed_classes( + method_worklist2, + namespacet(symbol_table), + ch, + needed_classes); std::set methods_already_populated; std::vector virtual_callsites; bool any_new_methods; - do { - + do + { any_new_methods=false; while(method_worklist2.size()!=0) { - std::swap(method_worklist1,method_worklist2); + std::swap(method_worklist1, method_worklist2); for(const auto& mname : method_worklist1) { if(!methods_already_populated.insert(mname).second) @@ -566,7 +588,9 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion( max_user_array_length, &method_worklist2, &needed_classes); - gather_virtual_callsites(symbol_table.lookup(mname).value,virtual_callsites); + gather_virtual_callsites( + symbol_table.lookup(mname).value, + virtual_callsites); any_new_methods=true; } method_worklist1.clear(); @@ -575,14 +599,16 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion( // Given the object types we now know may be created, populate more // possible virtual function call targets: - debug() << "CI lazy methods: add virtual method targets (" << virtual_callsites.size() << - " callsites)" << eom; + debug() << "CI lazy methods: add virtual method targets (" + << virtual_callsites.size() + << " callsites)" + << eom; for(const auto& callsite : virtual_callsites) { // This will also create a stub if a virtual callsite has no targets. - get_virtual_method_targets(*callsite,needed_classes,method_worklist2, - symbol_table,ch); + get_virtual_method_targets(*callsite, needed_classes, method_worklist2, + symbol_table, ch); } } while(any_new_methods); @@ -594,14 +620,20 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion( { if(sym.second.is_static_lifetime) continue; - if(lazy_methods.count(sym.first) && !methods_already_populated.count(sym.first)) + if(lazy_methods.count(sym.first) && + !methods_already_populated.count(sym.first)) + { continue; + } if(sym.second.type.id()==ID_code) - gather_needed_globals(sym.second.value,symbol_table,keep_symbols); + gather_needed_globals(sym.second.value, symbol_table, keep_symbols); keep_symbols.add(sym.second); } - debug() << "CI lazy methods: removed " << symbol_table.symbols.size() - keep_symbols.symbols.size() << " unreachable methods and globals" << eom; + debug() << "CI lazy methods: removed " + << symbol_table.symbols.size() - keep_symbols.symbols.size() + << " unreachable methods and globals" + << eom; symbol_table.swap(keep_symbols); diff --git a/src/java_bytecode/java_bytecode_language.h b/src/java_bytecode/java_bytecode_language.h index 750b92aa367..afdd275ddf6 100644 --- a/src/java_bytecode/java_bytecode_language.h +++ b/src/java_bytecode/java_bytecode_language.h @@ -23,7 +23,11 @@ enum lazy_methods_modet LAZY_METHODS_MODE_CONTEXT_SENSITIVE }; -typedef std::map > +typedef std::pair< + const symbolt*, + const java_bytecode_parse_treet::methodt*> + lazy_method_valuet; +typedef std::map lazy_methodst; class java_bytecode_languaget:public languaget From 9474d563dc07b8fe2763ef72431e4696fa81921b Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 9 Feb 2017 17:08:15 +0000 Subject: [PATCH 034/699] Add lazy loading tests --- regression/cbmc-java/lazyloading1/A.class | Bin 0 -> 222 bytes regression/cbmc-java/lazyloading1/B.class | Bin 0 -> 222 bytes regression/cbmc-java/lazyloading1/test.class | Bin 0 -> 292 bytes regression/cbmc-java/lazyloading1/test.desc | 8 +++++ regression/cbmc-java/lazyloading1/test.java | 21 +++++++++++++ regression/cbmc-java/lazyloading2/A.class | Bin 0 -> 222 bytes regression/cbmc-java/lazyloading2/B.class | Bin 0 -> 222 bytes regression/cbmc-java/lazyloading2/test.class | Bin 0 -> 310 bytes regression/cbmc-java/lazyloading2/test.desc | 8 +++++ regression/cbmc-java/lazyloading2/test.java | 23 ++++++++++++++ regression/cbmc-java/lazyloading3/A.class | Bin 0 -> 222 bytes regression/cbmc-java/lazyloading3/B.class | Bin 0 -> 222 bytes regression/cbmc-java/lazyloading3/C.class | Bin 0 -> 197 bytes regression/cbmc-java/lazyloading3/D.class | Bin 0 -> 197 bytes regression/cbmc-java/lazyloading3/test.class | Bin 0 -> 296 bytes regression/cbmc-java/lazyloading3/test.desc | 8 +++++ regression/cbmc-java/lazyloading3/test.java | 30 +++++++++++++++++++ 17 files changed, 98 insertions(+) create mode 100644 regression/cbmc-java/lazyloading1/A.class create mode 100644 regression/cbmc-java/lazyloading1/B.class create mode 100644 regression/cbmc-java/lazyloading1/test.class create mode 100644 regression/cbmc-java/lazyloading1/test.desc create mode 100644 regression/cbmc-java/lazyloading1/test.java create mode 100644 regression/cbmc-java/lazyloading2/A.class create mode 100644 regression/cbmc-java/lazyloading2/B.class create mode 100644 regression/cbmc-java/lazyloading2/test.class create mode 100644 regression/cbmc-java/lazyloading2/test.desc create mode 100644 regression/cbmc-java/lazyloading2/test.java create mode 100644 regression/cbmc-java/lazyloading3/A.class create mode 100644 regression/cbmc-java/lazyloading3/B.class create mode 100644 regression/cbmc-java/lazyloading3/C.class create mode 100644 regression/cbmc-java/lazyloading3/D.class create mode 100644 regression/cbmc-java/lazyloading3/test.class create mode 100644 regression/cbmc-java/lazyloading3/test.desc create mode 100644 regression/cbmc-java/lazyloading3/test.java diff --git a/regression/cbmc-java/lazyloading1/A.class b/regression/cbmc-java/lazyloading1/A.class new file mode 100644 index 0000000000000000000000000000000000000000..d6a62ca1ce465a6ae3fc35f9fa702cfa834ca298 GIT binary patch literal 222 zcmZXNy9&ZU5Jm6gVa!WyEd)!oFpZ@MB3OwQihUAS*$@+m8~@8nu3 zOQ{W4iHjO%@ih)$!DeDk=;%Aj!QtNc Vnm$}Ke`uF|tv@Ve*yV=-?*m^uqBqm`X_Sbr8+Ekm=tM6r!7<>R9O5A6#ILZBY z?k_p7_u~m*hK>glEeF1XHlZ<3i&QNL=4gB*SgZ0R3EfRv$ZdU&WOWcx&JHC6Z(r6` zEZ3A-v~jNyqM}hnO`)!EBM>9Vjr$$4#Ipfe)OD%LdK@30-UQ)r^KJ#@ zu}ke_w@&PKW|9?^aBW;F(65`_c5X+`YsJidW-m*#H!+IP3b!%tpc(dtpyI98%A_By zX|l9)O44U7&_s^E0|Hha5fM-*5CiaCXkv-e1G}*2pAV2P5Pq|~C2#H1Xc2xA%}16OcPq|~C2#H1Xc2xB@U16OcPq|~C2#H1Xc2xA%}16OcK literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/lazyloading3/B.class b/regression/cbmc-java/lazyloading3/B.class new file mode 100644 index 0000000000000000000000000000000000000000..9a4ab54d369d7175755e23dfabef5f15440bf383 GIT binary patch literal 222 zcmX^0Z`VEs1_l!bJ}w4k25xo+9(D#^Mg}&U%)HDJJ4Oa(4b3n{1{UZ1lvG9rexJ;| zRKL>Pq|~C2#H1Xc2xB@U16Occ5zb#DL54!6!+VDk(Sy*z4g7E1P33$hZ57`kdu7p zkmU1yy#XxXyU^j;=-KEKND%aBvm{unv`E#OaWXv-jIcaQf*+-Y+|}1uR!0%%?6`-r zt`fOT8*r4osd*;u!h;2y?}dax!$B^JOR$eKnJA2*@l$}f44D6k7ue}Ajkq_NIeUU0 PZS1gGtvO_MnKX2N4w)Zy literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/lazyloading3/D.class b/regression/cbmc-java/lazyloading3/D.class new file mode 100644 index 0000000000000000000000000000000000000000..7e16bd6527d6835776fcc14eb5132a4d94fcf1b2 GIT binary patch literal 197 zcmX^0Z`VEs1_l!bel7-P1|D_>UUmjPMh3FqHk-`6%n~~wS3@(5k%7fI zKP8osf!`-HFV(L!Hz~C!Brz!mD8dz-Us{x$>Xr%OaF(PNm*{0BmL>8quraU$&2wR7 z5CHM@a}x8?_5G8wQj<#<6d0I*mNGCf0x=5%E0hJ)02JW>@??QDNRCx&I|JiJurw!- QWCIII07)(&kBNaB01$#7eEKI~GBKD~_yhb= z#y2)@GV|WfelxS*Kc8O!?r>>P#z_@5)D2G2&}eG36ry{d`{F^N)a@-4!esmC6l$r@ z-DJPX+-`2OH7nu9`kZ(-O@;!R*>=BMy0MqXYT;gr+m(H_F(PPK|Bm2*(m!oDlp{D)`eOP3$G;8oD9r!> literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/lazyloading3/test.desc b/regression/cbmc-java/lazyloading3/test.desc new file mode 100644 index 00000000000..c0011248128 --- /dev/null +++ b/regression/cbmc-java/lazyloading3/test.desc @@ -0,0 +1,8 @@ +CORE +test.class +--lazy-methods --verbosity 10 --function test.main +^EXIT=0$ +^SIGNAL=0$ +elaborate java::A\.f:\(\)V +-- +elaborate java::B\.g:\(\)V diff --git a/regression/cbmc-java/lazyloading3/test.java b/regression/cbmc-java/lazyloading3/test.java new file mode 100644 index 00000000000..6d3129d1261 --- /dev/null +++ b/regression/cbmc-java/lazyloading3/test.java @@ -0,0 +1,30 @@ +// This test checks that because `main` has a parameter of type C, which has a field of type A, +// A::f is considered reachable, but B::g is not. + +public class test +{ + public static void main(C c) + { + c.a.f(); + } +} + +class A +{ + public void f() {} +} + +class B +{ + public void g() {} +} + +class C +{ + A a; +} + +class D +{ + B b; +} From 5c5bd7a43a0033999fc95efe62fed3fa9e561469 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 13 Feb 2017 11:08:22 +0000 Subject: [PATCH 035/699] Improve code style No functional changes intended --- src/goto-cc/compile.cpp | 6 +- src/goto-programs/get_goto_model.cpp | 4 +- .../java_bytecode_convert_class.cpp | 4 +- .../java_bytecode_convert_method.cpp | 16 +-- .../java_bytecode_convert_method.h | 2 +- src/java_bytecode/java_bytecode_language.cpp | 98 +++++++++---------- src/java_bytecode/java_entry_point.h | 2 +- src/langapi/language_ui.cpp | 4 +- src/util/language_file.cpp | 46 ++++----- src/util/language_file.h | 33 ++++--- 10 files changed, 110 insertions(+), 105 deletions(-) diff --git a/src/goto-cc/compile.cpp b/src/goto-cc/compile.cpp index f900b9824a7..04d50e76f82 100644 --- a/src/goto-cc/compile.cpp +++ b/src/goto-cc/compile.cpp @@ -544,8 +544,8 @@ bool compilet::parse(const std::string &file_name) language_filet language_file; - std::pair - res=language_files.filemap.insert( + std::pair + res=language_files.file_map.insert( std::pair(file_name, language_file)); language_filet &lf=res.first->second; @@ -736,7 +736,7 @@ bool compilet::parse_source(const std::string &file_name) return true; // so we remove it from the list afterwards - language_files.filemap.erase(file_name); + language_files.file_map.erase(file_name); return false; } diff --git a/src/goto-programs/get_goto_model.cpp b/src/goto-programs/get_goto_model.cpp index 5afef435596..02aae876030 100644 --- a/src/goto-programs/get_goto_model.cpp +++ b/src/goto-programs/get_goto_model.cpp @@ -75,8 +75,8 @@ bool get_goto_modelt::operator()(const std::vector &files) return true; } - std::pair - result=language_files.filemap.insert( + std::pair + result=language_files.file_map.insert( std::pair(filename, language_filet())); language_filet &lf=result.first->second; diff --git a/src/java_bytecode/java_bytecode_convert_class.cpp b/src/java_bytecode/java_bytecode_convert_class.cpp index eb642baa846..440b0ce32cf 100644 --- a/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/src/java_bytecode/java_bytecode_convert_class.cpp @@ -29,13 +29,13 @@ class java_bytecode_convert_classt:public messaget message_handlert &_message_handler, bool _disable_runtime_checks, size_t _max_array_length, - lazy_methodst& _lm, + lazy_methodst& _lazy_methods, lazy_methods_modet _lazy_methods_mode): messaget(_message_handler), symbol_table(_symbol_table), disable_runtime_checks(_disable_runtime_checks), max_array_length(_max_array_length), - lazy_methods(_lm), + lazy_methods(_lazy_methods), lazy_methods_mode(_lazy_methods_mode) { } diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 79db9de0f03..bc12fc77617 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -201,10 +201,10 @@ Function: java_bytecode_convert_method_lazy \*******************************************************************/ void java_bytecode_convert_method_lazy( - const symbolt& class_symbol, - const irep_idt method_identifier, + const symbolt &class_symbol, + const irep_idt &method_identifier, const java_bytecode_parse_treet::methodt &m, - symbol_tablet& symbol_table) + symbol_tablet &symbol_table) { symbolt method_symbol; typet member_type=java_type_from_string(m.signature); @@ -217,12 +217,14 @@ void java_bytecode_convert_method_lazy( if(method_symbol.base_name=="") { - method_symbol.pretty_name=id2string(class_symbol.pretty_name)+"."+ - id2string(class_symbol.base_name)+"()"; + method_symbol.pretty_name= + id2string(class_symbol.pretty_name)+"."+ + id2string(class_symbol.base_name)+"()"; member_type.set(ID_constructor, true); } else - method_symbol.pretty_name=id2string(class_symbol.pretty_name)+"."+ + method_symbol.pretty_name= + id2string(class_symbol.pretty_name)+"."+ id2string(m.base_name)+"()"; // do we need to add 'this' as a parameter? @@ -261,7 +263,7 @@ void java_bytecode_convert_methodt::convert( id2string(class_symbol.name)+"."+id2string(m.name)+":"+m.signature; method_id=method_identifier; - const auto& old_sym=symbol_table.lookup(method_identifier); + const auto &old_sym=symbol_table.lookup(method_identifier); typet member_type=old_sym.type; code_typet &code_type=to_code_type(member_type); diff --git a/src/java_bytecode/java_bytecode_convert_method.h b/src/java_bytecode/java_bytecode_convert_method.h index 145c7a5cc91..68b0dd4e0a8 100644 --- a/src/java_bytecode/java_bytecode_convert_method.h +++ b/src/java_bytecode/java_bytecode_convert_method.h @@ -48,7 +48,7 @@ inline void java_bytecode_convert_method( void java_bytecode_convert_method_lazy( const symbolt &class_symbol, - const irep_idt method_identifier, + const irep_idt &method_identifier, const java_bytecode_parse_treet::methodt &, symbol_tablet &symbol_table); diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index c9f1b1771d2..4512ec97709 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -156,7 +156,7 @@ bool java_bytecode_languaget::parse( { status() << "JAR file without entry point: loading it all" << eom; java_class_loader.load_entire_jar(path); - for(const auto& kv : java_class_loader.jar_map.at(path).entries) + for(const auto &kv : java_class_loader.jar_map.at(path).entries) main_jar_classes.push_back(kv.first); } else @@ -201,10 +201,10 @@ Function: get_virtual_method_target \*******************************************************************/ static irep_idt get_virtual_method_target( - const std::set& needed_classes, - const irep_idt& call_basename, - const irep_idt& classname, - const symbol_tablet& symbol_table) + const std::set &needed_classes, + const irep_idt &call_basename, + const irep_idt &classname, + const symbol_tablet &symbol_table) { // Program-wide, is this class ever instantiated? if(!needed_classes.count(classname)) @@ -238,24 +238,24 @@ Function: get_virtual_method_target \*******************************************************************/ static void get_virtual_method_targets( - const code_function_callt& c, - const std::set& needed_classes, - std::vector& needed_methods, - symbol_tablet& symbol_table, - const class_hierarchyt& class_hierarchy) + const code_function_callt &c, + const std::set &needed_classes, + std::vector &needed_methods, + symbol_tablet &symbol_table, + const class_hierarchyt &class_hierarchy) { - const auto& called_function=c.function(); + const auto &called_function=c.function(); assert(called_function.id()==ID_virtual_function); - const auto& call_class=called_function.get(ID_C_class); + const auto &call_class=called_function.get(ID_C_class); assert(call_class!=irep_idt()); - const auto& call_basename=called_function.get(ID_component_name); + const auto &call_basename=called_function.get(ID_component_name); assert(call_basename!=irep_idt()); auto old_size=needed_methods.size(); auto child_classes=class_hierarchy.get_children_trans(call_class); - for(const auto& child_class : child_classes) + for(const auto &child_class : child_classes) { auto child_method= get_virtual_method_target( @@ -288,8 +288,8 @@ static void get_virtual_method_targets( break; else { - const auto& entry=findit->second; - if(entry.parents.size()==0) + const auto &entry=findit->second; + if(entry.parents.empty()) break; else parent_class_id=entry.parents[0]; @@ -325,12 +325,12 @@ Function: gather_virtual_callsites \*******************************************************************/ static void gather_virtual_callsites( - const exprt& e, - std::vector& result) + const exprt &e, + std::vector &result) { if(e.id()!=ID_code) return; - const codet& c=to_code(e); + const codet &c=to_code(e); if(c.get_statement()==ID_function_call && to_code_function_call(c).function().id()==ID_virtual_function) result.push_back(&to_code_function_call(c)); @@ -354,13 +354,13 @@ Function: gather_needed_globals \*******************************************************************/ static void gather_needed_globals( - const exprt& e, - const symbol_tablet& symbol_table, - symbol_tablet& needed) + const exprt &e, + const symbol_tablet &symbol_table, + symbol_tablet &needed) { if(e.id()==ID_symbol) { - const auto& sym=symbol_table.lookup(to_symbol_expr(e).get_identifier()); + const auto &sym=symbol_table.lookup(to_symbol_expr(e).get_identifier()); if(sym.is_static_lifetime) needed.add(sym); } @@ -387,12 +387,12 @@ Function: gather_field_types \*******************************************************************/ static void gather_field_types( - const typet& class_type, - const namespacet& ns, - std::set& needed_classes) + const typet &class_type, + const namespacet &ns, + std::set &needed_classes) { - const auto& underlying_type=to_struct_type(ns.follow(class_type)); - for(const auto& field : underlying_type.components()) + const auto &underlying_type=to_struct_type(ns.follow(class_type)); + for(const auto &field : underlying_type.components()) { if(field.type().id()==ID_struct || field.type().id()==ID_symbol) gather_field_types(field.type(), ns, needed_classes); @@ -401,7 +401,7 @@ static void gather_field_types( // Skip array primitive pointers, for example: if(field.type().subtype().id()!=ID_symbol) continue; - const auto& field_classid= + const auto &field_classid= to_symbol_type(field.type().subtype()).get_identifier(); if(needed_classes.insert(field_classid).second) gather_field_types(field.type().subtype(), ns, needed_classes); @@ -411,7 +411,7 @@ static void gather_field_types( /*******************************************************************\ -Function: initialise_needed_classes +Function: initialize_needed_classes Inputs: `entry_points`: list of fully-qualified function names that we should assume are reachable @@ -426,26 +426,26 @@ Function: initialise_needed_classes \*******************************************************************/ -static void initialise_needed_classes( - const std::vector& entry_points, - const namespacet& ns, - const class_hierarchyt& ch, - std::set& needed_classes) +static void initialize_needed_classes( + const std::vector &entry_points, + const namespacet &ns, + const class_hierarchyt &ch, + std::set &needed_classes) { - for(const auto& mname : entry_points) + for(const auto &mname : entry_points) { - const auto& symbol=ns.lookup(mname); - const auto& mtype=to_code_type(symbol.type); - for(const auto& param : mtype.parameters()) + const auto &symbol=ns.lookup(mname); + const auto &mtype=to_code_type(symbol.type); + for(const auto ¶m : mtype.parameters()) { if(param.type().id()==ID_pointer) { - const auto& param_classid= + const auto ¶m_classid= to_symbol_type(param.type().subtype()).get_identifier(); std::vector class_and_parents= ch.get_parents_trans(param_classid); class_and_parents.push_back(param_classid); - for(const auto& classid : class_and_parents) + for(const auto &classid : class_and_parents) needed_classes.insert(classid); gather_field_types(param.type().subtype(), ns, needed_classes); } @@ -534,11 +534,11 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion( reachable_classes.push_back(main_class); else reachable_classes=main_jar_classes; - for(const auto& classname : reachable_classes) + for(const auto &classname : reachable_classes) { - const auto& methods= + const auto &methods= java_class_loader.class_map.at(classname).parsed_class.methods; - for(const auto& method : methods) + for(const auto &method : methods) { const irep_idt methodid="java::"+id2string(classname)+"."+ id2string(method.name)+":"+ @@ -551,7 +551,7 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion( method_worklist2.push_back(main_function.main_function.name); std::set needed_classes; - initialise_needed_classes( + initialize_needed_classes( method_worklist2, namespacet(symbol_table), ch, @@ -567,7 +567,7 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion( while(method_worklist2.size()!=0) { std::swap(method_worklist1, method_worklist2); - for(const auto& mname : method_worklist1) + for(const auto &mname : method_worklist1) { if(!methods_already_populated.insert(mname).second) continue; @@ -578,7 +578,7 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion( continue; } debug() << "CI lazy methods: elaborate " << mname << eom; - const auto& parsed_method=findit->second; + const auto &parsed_method=findit->second; java_bytecode_convert_method( *parsed_method.first, *parsed_method.second, @@ -604,7 +604,7 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion( << " callsites)" << eom; - for(const auto& callsite : virtual_callsites) + for(const auto &callsite : virtual_callsites) { // This will also create a stub if a virtual callsite has no targets. get_virtual_method_targets(*callsite, needed_classes, method_worklist2, @@ -616,7 +616,7 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion( // Remove symbols for methods that were declared but never used: symbol_tablet keep_symbols; - for(const auto& sym : symbol_table.symbols) + for(const auto &sym : symbol_table.symbols) { if(sym.second.is_static_lifetime) continue; diff --git a/src/java_bytecode/java_entry_point.h b/src/java_bytecode/java_entry_point.h index 82071aa26b1..e6575734d80 100644 --- a/src/java_bytecode/java_entry_point.h +++ b/src/java_bytecode/java_entry_point.h @@ -29,6 +29,6 @@ main_function_resultt get_main_symbol( symbol_tablet &symbol_table, const irep_idt &main_class, message_handlert &, - bool allow_no_body = false); + bool allow_no_body=false); #endif // CPROVER_JAVA_BYTECODE_JAVA_ENTRY_POINT_H diff --git a/src/langapi/language_ui.cpp b/src/langapi/language_ui.cpp index 8640d735631..95b5d104a4f 100644 --- a/src/langapi/language_ui.cpp +++ b/src/langapi/language_ui.cpp @@ -104,8 +104,8 @@ bool language_uit::parse(const std::string &filename) return true; } - std::pair - result=language_files.filemap.insert( + std::pair + result=language_files.file_map.insert( std::pair(filename, language_filet())); language_filet &lf=result.first->second; diff --git a/src/util/language_file.cpp b/src/util/language_file.cpp index 5ecbf9b7438..46f51564b54 100644 --- a/src/util/language_file.cpp +++ b/src/util/language_file.cpp @@ -67,9 +67,9 @@ void language_filet::get_modules() void language_filet::convert_lazy_method( const irep_idt &id, - symbol_tablet &symtab) + symbol_tablet &symbol_table) { - language->convert_lazy_method(id, symtab); + language->convert_lazy_method(id, symbol_table); } /*******************************************************************\ @@ -86,8 +86,8 @@ Function: language_filest::show_parse void language_filest::show_parse(std::ostream &out) { - for(filemapt::iterator it=filemap.begin(); - it!=filemap.end(); it++) + for(file_mapt::iterator it=file_map.begin(); + it!=file_map.end(); it++) it->second.language->show_parse(out); } @@ -105,8 +105,8 @@ Function: language_filest::parse bool language_filest::parse() { - for(filemapt::iterator it=filemap.begin(); - it!=filemap.end(); it++) + for(file_mapt::iterator it=file_map.begin(); + it!=file_map.end(); it++) { // open file @@ -152,8 +152,8 @@ bool language_filest::typecheck(symbol_tablet &symbol_table) { // typecheck interfaces - for(filemapt::iterator it=filemap.begin(); - it!=filemap.end(); it++) + for(file_mapt::iterator it=file_map.begin(); + it!=file_map.end(); it++) { if(it->second.language->interfaces(symbol_table)) return true; @@ -163,8 +163,8 @@ bool language_filest::typecheck(symbol_tablet &symbol_table) unsigned collision_counter=0; - for(filemapt::iterator fm_it=filemap.begin(); - fm_it!=filemap.end(); fm_it++) + for(file_mapt::iterator fm_it=file_map.begin(); + fm_it!=file_map.end(); fm_it++) { const language_filet::modulest &modules= fm_it->second.modules; @@ -177,7 +177,7 @@ bool language_filest::typecheck(symbol_tablet &symbol_table) // these may collide, and then get renamed std::string module_name=*mo_it; - while(modulemap.find(module_name)!=modulemap.end()) + while(module_map.find(module_name)!=module_map.end()) { module_name=*mo_it+"#"+std::to_string(collision_counter); collision_counter++; @@ -186,15 +186,15 @@ bool language_filest::typecheck(symbol_tablet &symbol_table) language_modulet module; module.file=&fm_it->second; module.name=module_name; - modulemap.insert( + module_map.insert( std::pair(module.name, module)); } } // typecheck files - for(filemapt::iterator it=filemap.begin(); - it!=filemap.end(); it++) + for(file_mapt::iterator it=file_map.begin(); + it!=file_map.end(); it++) { if(it->second.modules.empty()) { @@ -206,14 +206,14 @@ bool language_filest::typecheck(symbol_tablet &symbol_table) std::set lazy_method_ids; it->second.language->lazy_methods_provided(lazy_method_ids); for(const auto &id : lazy_method_ids) - lazymethodmap[id]=&it->second; + lazy_method_map[id]=&it->second; } } // typecheck modules - for(modulemapt::iterator it=modulemap.begin(); - it!=modulemap.end(); it++) + for(module_mapt::iterator it=module_map.begin(); + it!=module_map.end(); it++) { if(typecheck_module(symbol_table, it->second)) return true; @@ -239,8 +239,8 @@ bool language_filest::final( { std::set languages; - for(filemapt::iterator it=filemap.begin(); - it!=filemap.end(); it++) + for(file_mapt::iterator it=file_map.begin(); + it!=file_map.end(); it++) { if(languages.insert(it->second.language->id()).second) if(it->second.language->final(symbol_table)) @@ -265,8 +265,8 @@ Function: language_filest::interfaces bool language_filest::interfaces( symbol_tablet &symbol_table) { - for(filemapt::iterator it=filemap.begin(); - it!=filemap.end(); it++) + for(file_mapt::iterator it=file_map.begin(); + it!=file_map.end(); it++) { if(it->second.language->interfaces(symbol_table)) return true; @@ -293,9 +293,9 @@ bool language_filest::typecheck_module( { // check module map - modulemapt::iterator it=modulemap.find(module); + module_mapt::iterator it=module_map.find(module); - if(it==modulemap.end()) + if(it==module_map.end()) { error() << "found no file that provides module " << module << eom; return true; diff --git a/src/util/language_file.h b/src/util/language_file.h index b538c24e84f..d3184d48697 100644 --- a/src/util/language_file.h +++ b/src/util/language_file.h @@ -44,7 +44,7 @@ class language_filet void convert_lazy_method( const irep_idt &id, - symbol_tablet &symtab); + symbol_tablet &symbol_table); language_filet(const language_filet &rhs); @@ -58,21 +58,21 @@ class language_filet class language_filest:public messaget { public: - typedef std::map filemapt; - filemapt filemap; + typedef std::map file_mapt; + file_mapt file_map; - // Contains pointers into filemapt! - typedef std::map modulemapt; - modulemapt modulemap; + // Contains pointers into file_mapt! + typedef std::map module_mapt; + module_mapt module_map; // Contains pointers into filemapt! // This is safe-ish as long as this is std::map. - typedef std::map lazymethodmapt; - lazymethodmapt lazymethodmap; + typedef std::map lazy_method_mapt; + lazy_method_mapt lazy_method_map; void clear_files() { - filemap.clear(); + file_map.clear(); } bool parse(); @@ -87,21 +87,24 @@ class language_filest:public messaget bool has_lazy_method(const irep_idt &id) { - return lazymethodmap.count(id); + return lazy_method_map.count(id); } + // The method must have been added to the symbol table and registered + // in lazy_method_map (currently always in language_filest::typecheck) + // for this to be legal. void convert_lazy_method( const irep_idt &id, - symbol_tablet &symtab) + symbol_tablet &symbol_table) { - return lazymethodmap.at(id)->convert_lazy_method(id, symtab); + return lazy_method_map.at(id)->convert_lazy_method(id, symbol_table); } void clear() { - filemap.clear(); - modulemap.clear(); - lazymethodmap.clear(); + file_map.clear(); + module_map.clear(); + lazy_method_map.clear(); } protected: From 86bef2317d14b10cec6f86dcafc1355f5f30d421 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 15 Feb 2017 11:34:20 +0000 Subject: [PATCH 036/699] Use safe pointers for optional arguments This basic safe-pointer class doesn't do any lifetime management; rather it just enforces explicit null-checks and throws if they don't go as expected. --- .../java_bytecode_convert_method.cpp | 12 ++-- .../java_bytecode_convert_method.h | 9 +-- .../java_bytecode_convert_method_class.h | 9 +-- src/java_bytecode/java_bytecode_language.cpp | 4 +- src/util/safe_pointer.h | 64 +++++++++++++++++++ 5 files changed, 84 insertions(+), 14 deletions(-) create mode 100644 src/util/safe_pointer.h diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index bc12fc77617..ed87954ed0b 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -1724,7 +1724,10 @@ codet java_bytecode_convert_methodt::convert_instructions( const auto &field_name=arg0.get_string(ID_component_name); symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+field_name); if(needed_classes && arg0.type().id()==ID_symbol) - needed_classes->insert(to_symbol_type(arg0.type()).get_identifier()); + { + needed_classes->insert( + to_symbol_type(arg0.type()).get_identifier()); + } results[0]=java_bytecode_promotion(symbol_expr); // set $assertionDisabled to false @@ -1743,7 +1746,8 @@ codet java_bytecode_convert_methodt::convert_instructions( const auto &field_name=arg0.get_string(ID_component_name); symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+field_name); if(needed_classes && arg0.type().id()==ID_symbol) - needed_classes->insert(to_symbol_type(arg0.type()).get_identifier()); + needed_classes->insert( + to_symbol_type(arg0.type()).get_identifier()); c=code_assignt(symbol_expr, op[0]); } else if(statement==patternt("?2?")) // i2c etc. @@ -2207,8 +2211,8 @@ void java_bytecode_convert_method( message_handlert &message_handler, bool disable_runtime_checks, size_t max_array_length, - std::vector *needed_methods, - std::set *needed_classes) + safe_pointer > needed_methods, + safe_pointer > needed_classes) { java_bytecode_convert_methodt java_bytecode_convert_method( symbol_table, diff --git a/src/java_bytecode/java_bytecode_convert_method.h b/src/java_bytecode/java_bytecode_convert_method.h index 68b0dd4e0a8..e81881f44e1 100644 --- a/src/java_bytecode/java_bytecode_convert_method.h +++ b/src/java_bytecode/java_bytecode_convert_method.h @@ -11,6 +11,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include #include "java_bytecode_parse_tree.h" @@ -23,8 +24,8 @@ void java_bytecode_convert_method( message_handlert &message_handler, bool disable_runtime_checks, size_t max_array_length, - std::vector *needed_methods, - std::set *needed_classes); + safe_pointer > needed_methods, + safe_pointer > needed_classes); // Must provide both the optional parameters or neither. inline void java_bytecode_convert_method( @@ -42,8 +43,8 @@ inline void java_bytecode_convert_method( message_handler, disable_runtime_checks, max_array_length, - nullptr, - nullptr); + safe_pointer >::create_null(), + safe_pointer >::create_null()); } void java_bytecode_convert_method_lazy( diff --git a/src/java_bytecode/java_bytecode_convert_method_class.h b/src/java_bytecode/java_bytecode_convert_method_class.h index 96e640ecdf3..ae4ba711640 100644 --- a/src/java_bytecode/java_bytecode_convert_method_class.h +++ b/src/java_bytecode/java_bytecode_convert_method_class.h @@ -13,6 +13,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include #include #include "java_bytecode_parse_tree.h" #include "java_bytecode_convert_class.h" @@ -31,8 +32,8 @@ class java_bytecode_convert_methodt:public messaget message_handlert &_message_handler, bool _disable_runtime_checks, size_t _max_array_length, - std::vector *_needed_methods, - std::set *_needed_classes): + safe_pointer > _needed_methods, + safe_pointer > _needed_classes): messaget(_message_handler), symbol_table(_symbol_table), disable_runtime_checks(_disable_runtime_checks), @@ -57,8 +58,8 @@ class java_bytecode_convert_methodt:public messaget symbol_tablet &symbol_table; const bool disable_runtime_checks; const size_t max_array_length; - std::vector *needed_methods; - std::set *needed_classes; + safe_pointer > needed_methods; + safe_pointer > needed_classes; irep_idt method_id; irep_idt current_method; diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index 4512ec97709..03b5a51a4a2 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -586,8 +586,8 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion( get_message_handler(), disable_runtime_checks, max_user_array_length, - &method_worklist2, - &needed_classes); + safe_pointer >::create_non_null(&method_worklist2), + safe_pointer >::create_non_null(&needed_classes)); gather_virtual_callsites( symbol_table.lookup(mname).value, virtual_callsites); diff --git a/src/util/safe_pointer.h b/src/util/safe_pointer.h new file mode 100644 index 00000000000..47e52ac13fe --- /dev/null +++ b/src/util/safe_pointer.h @@ -0,0 +1,64 @@ +/*******************************************************************\ + +Module: Simple checked pointers + +Author: Chris Smowton, chris@smowton.net + +\*******************************************************************/ + +#ifndef CPROVER_UTIL_SAFE_POINTER_H +#define CPROVER_UTIL_SAFE_POINTER_H + +template class safe_pointer +{ + public: + operator bool() const + { + return !!ptr; + } + + T *get() const + { + assert(ptr && "dereferenced a null safe pointer"); + return ptr; + } + + T &operator*() const + { + return *get(); + } + + T *operator->() const + { + return get(); + } + + static safe_pointer create_null() + { + return safe_pointer(); + } + + static safe_pointer create_non_null( + T *target) + { + assert(target && "initialized safe pointer with null"); + return safe_pointer(target); + } + + static safe_pointer create_maybe_null( + T *target) + { + return safe_pointer(target); + } + + protected: + T *ptr; + + explicit safe_pointer(T *target) : ptr(target) + {} + + safe_pointer() : ptr(nullptr) + {} +}; + +#endif From ffef5d715dbde87696151ed6cc501e1f391aeb12 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 15 Feb 2017 12:58:30 +0000 Subject: [PATCH 037/699] Add lazy conversion documentation Also fix some trivial linting errors. No functional changes. --- .../java_bytecode_convert_method.cpp | 2 + src/java_bytecode/java_bytecode_language.cpp | 86 +++++++++++++++++-- src/java_bytecode/java_bytecode_language.h | 4 +- 3 files changed, 82 insertions(+), 10 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index ed87954ed0b..f101d19c824 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -1746,8 +1746,10 @@ codet java_bytecode_convert_methodt::convert_instructions( const auto &field_name=arg0.get_string(ID_component_name); symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+field_name); if(needed_classes && arg0.type().id()==ID_symbol) + { needed_classes->insert( to_symbol_type(arg0.type()).get_identifier()); + } c=code_assignt(symbol_expr, op[0]); } else if(statement==patternt("?2?")) // i2c etc. diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index 03b5a51a4a2..e9d5a87186b 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -502,6 +502,7 @@ bool java_bytecode_languaget::typecheck( // that are reachable from this entry point. if(lazy_methods_mode==LAZY_METHODS_MODE_CONTEXT_INSENSITIVE) { + // ci: context-insensitive. if(do_ci_lazy_method_conversion(symbol_table, lazy_methods)) return true; } @@ -514,6 +515,32 @@ bool java_bytecode_languaget::typecheck( return false; } +/*******************************************************************\ + +Function: java_bytecode_languaget::do_ci_lazy_method_conversion + + Inputs: `symbol_table`: global symbol table + `lazy_methods`: map from method names to relevant symbol + and parsed-method objects. + + Outputs: Elaborates lazily-converted methods that may be reachable + starting from the main entry point (usually provided with + the --function command-line option) (side-effect on the + symbol_table). Returns false on success. + + Purpose: Uses a simple context-insensitive ('ci') analysis to + determine which methods may be reachable from the main + entry point. In brief, static methods are reachable if we + find a callsite in another reachable site, while virtual + methods are reachable if we find a virtual callsite + targeting a compatible type *and* a constructor callsite + indicating an object of that type may be instantiated (or + evidence that an object of that type exists before the + main function is entered, such as being passed as a + parameter). + +\*******************************************************************/ + bool java_bytecode_languaget::do_ci_lazy_method_conversion( symbol_tablet &symbol_table, lazy_methodst &lazy_methods) @@ -558,7 +585,7 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion( needed_classes); std::set methods_already_populated; - std::vector virtual_callsites; + std::vector virtual_callsites; bool any_new_methods; do @@ -586,8 +613,10 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion( get_message_handler(), disable_runtime_checks, max_user_array_length, - safe_pointer >::create_non_null(&method_worklist2), - safe_pointer >::create_non_null(&needed_classes)); + safe_pointer >::create_non_null( + &method_worklist2), + safe_pointer >::create_non_null( + &needed_classes)); gather_virtual_callsites( symbol_table.lookup(mname).value, virtual_callsites); @@ -607,11 +636,15 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion( for(const auto &callsite : virtual_callsites) { // This will also create a stub if a virtual callsite has no targets. - get_virtual_method_targets(*callsite, needed_classes, method_worklist2, - symbol_table, ch); + get_virtual_method_targets( + *callsite, + needed_classes, + method_worklist2, + symbol_table, + ch); } - - } while(any_new_methods); + } + while(any_new_methods); // Remove symbols for methods that were declared but never used: symbol_tablet keep_symbols; @@ -640,12 +673,49 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion( return false; } -void java_bytecode_languaget::lazy_methods_provided(std::set &methods) const +/*******************************************************************\ + +Function: java_bytecode_languaget::lazy_methods_provided + + Inputs: None + + Outputs: Populates `methods` with the complete list of lazy methods + that are available to convert (those which are valid + parameters for `convert_lazy_method`) + + Purpose: Provide feedback to `language_filest` so that when asked + for a lazy method, it can delegate to this instance of + java_bytecode_languaget. + +\*******************************************************************/ + +void java_bytecode_languaget::lazy_methods_provided( + std::set &methods) const { for(const auto &kv : lazy_methods) methods.insert(kv.first); } +/*******************************************************************\ + +Function: java_bytecode_languaget::convert_lazy_method + + Inputs: `id`: method ID to convert + `symtab`: global symbol table + + Outputs: Amends the symbol table entry for function `id`, which + should be a lazy method provided by this instance of + `java_bytecode_languaget`. It should initially have a nil + value. After this method completes, it will have a value + representing the method body, identical to that produced + using eager method conversion. + + Purpose: Promote a lazy-converted method (one whose type is known + but whose body hasn't been converted) into a fully- + elaborated one. + +\*******************************************************************/ + void java_bytecode_languaget::convert_lazy_method( const irep_idt &id, symbol_tablet &symtab) diff --git a/src/java_bytecode/java_bytecode_language.h b/src/java_bytecode/java_bytecode_language.h index afdd275ddf6..ea177e0226a 100644 --- a/src/java_bytecode/java_bytecode_language.h +++ b/src/java_bytecode/java_bytecode_language.h @@ -24,8 +24,8 @@ enum lazy_methods_modet }; typedef std::pair< - const symbolt*, - const java_bytecode_parse_treet::methodt*> + const symbolt *, + const java_bytecode_parse_treet::methodt *> lazy_method_valuet; typedef std::map lazy_methodst; From a30720b39e3597875ee476840523d2d31c0a9a5f Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 15 Feb 2017 17:28:55 +0000 Subject: [PATCH 038/699] Improve failed test printer --- regression/failed-tests-printer.pl | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/regression/failed-tests-printer.pl b/regression/failed-tests-printer.pl index 832ba2d2c64..40767185d5c 100755 --- a/regression/failed-tests-printer.pl +++ b/regression/failed-tests-printer.pl @@ -4,23 +4,25 @@ open LOG,") { chomp; if (/^Test '(.+)'/) { $current_test = $1; - $ignore = 0; - } elsif (1 == $ignore) { - next; + $printed_this_test = 0; } elsif (/\[FAILED\]\s*$/) { - $ignore = 1; - print "Failed test: $current_test\n"; - my $outf = `sed -n '2p' $current_test/test.desc`; - $outf =~ s/\..*$/.out/; - system("cat $current_test/$outf"); - print "\n\n"; + if(0 == $printed_this_test) { + $printed_this_test = 1; + print "\n\n"; + print "Failed test: $current_test\n"; + my $outf = `sed -n '2p' $current_test/test.desc`; + $outf =~ s/\..*$/.out/; + system("cat $current_test/$outf"); + print "\n\nFailed test.desc lines:\n"; + } + print "$_\n"; } } From 8809a4c56820dd74bc52834655e0c2639919d40a Mon Sep 17 00:00:00 2001 From: Norbert Manthey Date: Tue, 28 Feb 2017 23:17:12 +0100 Subject: [PATCH 039/699] Remove aa-symex from DIRS variable in Makefile Without this patch, calling "make clean" fails, because make tries to call "make clean" in the aa-symex directory as well. By removing aa-symex from the DIRS variable, this problem is fixed. Fixes: cleanup aa-path-symex and aa-symex --- src/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index 3a452b7fe09..269ddeda140 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,7 +1,7 @@ DIRS = ansi-c big-int cbmc cpp goto-cc goto-instrument goto-programs \ goto-symex langapi pointer-analysis solvers util linking xmllang \ - assembler analyses java_bytecode aa-path-symex path-symex musketeer \ - json cegis goto-analyzer jsil symex goto-diff aa-symex clobber \ + assembler analyses java_bytecode path-symex musketeer \ + json cegis goto-analyzer jsil symex goto-diff clobber \ memory-models all: cbmc.dir goto-cc.dir goto-instrument.dir symex.dir goto-analyzer.dir goto-diff.dir From 6c0ff32172d56335deebc5044ea3eacac3faf824 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 29 Nov 2016 14:50:47 +0000 Subject: [PATCH 040/699] Don't allowing functions called from _Start to be inlined When the partial inlining comes to the _Start function, it skips over it. We don't want inlining on the start function because if we are trying to find the entry point for the users code, it is important it hasn't been inlined into GOTO generated code. --- src/goto-programs/goto_inline.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/goto-programs/goto_inline.cpp b/src/goto-programs/goto_inline.cpp index 830798c289e..c8c97f8d4a5 100644 --- a/src/goto-programs/goto_inline.cpp +++ b/src/goto-programs/goto_inline.cpp @@ -213,7 +213,12 @@ void goto_partial_inline( // called function const goto_functiont &goto_function=f_it->second; - if(!goto_function.body_available()) + // We can't take functions without bodies to find functions + // inside them to be inlined. + // We also don't allow for the _start function to have any of its + // function calls to be inlined + if(!goto_function.body_available() || + f_it->first==ID__start) continue; const goto_programt &goto_program=goto_function.body; From d47d503b660386e840ed41e3fe5ba9dd7ef0dfd5 Mon Sep 17 00:00:00 2001 From: Dario Cattaruzza Date: Tue, 25 Oct 2016 16:14:56 +0100 Subject: [PATCH 041/699] Get symbol of member expression --- src/util/std_expr.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/util/std_expr.h b/src/util/std_expr.h index a2f78ab25e8..30296525585 100644 --- a/src/util/std_expr.h +++ b/src/util/std_expr.h @@ -2979,6 +2979,17 @@ class member_exprt:public exprt { return op0(); } + + // Retrieves the object(symbol) this member corresponds to + inline const symbol_exprt &symbol() const + { + const exprt &op=op0(); + if(op.id()==ID_member) + { + return static_cast(op).symbol(); + } + return to_symbol_expr(op); + } }; /*! \brief Cast a generic exprt to a \ref member_exprt From 27153d142eb07dc0e78eb47d72e52b877af5d776 Mon Sep 17 00:00:00 2001 From: Dario Cattaruzza Date: Tue, 25 Oct 2016 16:16:43 +0100 Subject: [PATCH 042/699] Auxiliary function to check if the ssa has enough data to build an identifier --- src/util/ssa_expr.cpp | 13 +++++++++++++ src/util/ssa_expr.h | 6 +++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/util/ssa_expr.cpp b/src/util/ssa_expr.cpp index c75d7d2ed92..affd2907eb5 100644 --- a/src/util/ssa_expr.cpp +++ b/src/util/ssa_expr.cpp @@ -78,6 +78,19 @@ static void build_ssa_identifier_rec( assert(false); } +/* Used to determine whether or not an identifier can be built + * before trying and getting an exception */ +bool ssa_exprt::can_build_identifier(const exprt &expr) +{ + if(expr.id()==ID_symbol) + return true; + else if(expr.id()==ID_member || + expr.id()==ID_index) + return can_build_identifier(expr.op0()); + else + return false; +} + /*******************************************************************\ Function: ssa_exprt::build_identifier diff --git a/src/util/ssa_expr.h b/src/util/ssa_expr.h index 446e82169d6..e18862fa9f9 100644 --- a/src/util/ssa_expr.h +++ b/src/util/ssa_expr.h @@ -64,7 +64,7 @@ class ssa_exprt:public symbol_exprt const irep_idt get_l1_object_identifier() const { - #if 0 + #if 1 return get_l1_object().get_identifier(); #else // the above is the clean version, this is the fast one, using @@ -134,6 +134,10 @@ class ssa_exprt:public symbol_exprt const irep_idt &l0, const irep_idt &l1, const irep_idt &l2); + + /* Used to determine whether or not an identifier can be built + * before trying and getting an exception */ + static bool can_build_identifier(const exprt &src); }; /*! \brief Cast a generic exprt to an \ref ssa_exprt From 2987406470da274a1f75024251bc07650352465c Mon Sep 17 00:00:00 2001 From: Dario Cattaruzza Date: Tue, 25 Oct 2016 16:17:06 +0100 Subject: [PATCH 043/699] Bitwise operators for mpinteger --- src/util/mp_arith.cpp | 264 ++++++++++++++++++++++++++++++++++++++++++ src/util/mp_arith.h | 23 ++++ 2 files changed, 287 insertions(+) diff --git a/src/util/mp_arith.cpp b/src/util/mp_arith.cpp index 338a6103e40..e70c654bd14 100644 --- a/src/util/mp_arith.cpp +++ b/src/util/mp_arith.cpp @@ -17,6 +17,9 @@ Author: Daniel Kroening, kroening@kroening.com #include "mp_arith.h" #include "arith_tools.h" + +typedef BigInt::ullong_t ullong_t; + /*******************************************************************\ Function: >> @@ -320,3 +323,264 @@ unsigned integer2unsigned(const mp_integer &n) assert(ull <= std::numeric_limits::max()); return (unsigned)ull; } + +/*******************************************************************\ + +Function: bitwise_or + + Inputs: + + Outputs: + + Purpose: bitwise or + bitwise operations only make sense on native objects, hence the + largest object size should be the largest available c++ integer + size (currently long long) + +\*******************************************************************/ + +mp_integer bitwise_or(const mp_integer &a, const mp_integer &b) +{ + ullong_t result=a.to_ulong()|b.to_ulong(); + return result; +} + +/*******************************************************************\ + +Function: bitwise_and + + Inputs: + + Outputs: + + Purpose: bitwise and + bitwise operations only make sense on native objects, hence the + largest object size should be the largest available c++ integer + size (currently long long) + +\*******************************************************************/ + +mp_integer bitwise_and(const mp_integer &a, const mp_integer &b) +{ + ullong_t result=a.to_ulong()&b.to_ulong(); + return result; +} + +/*******************************************************************\ + +Function: bitwise_xor + + Inputs: + + Outputs: + + Purpose: bitwise xor + bitwise operations only make sense on native objects, hence the + largest object size should be the largest available c++ integer + size (currently long long) + +\*******************************************************************/ + +mp_integer bitwise_xor(const mp_integer &a, const mp_integer &b) +{ + ullong_t result=a.to_ulong()^b.to_ulong(); + return result; +} + +/*******************************************************************\ + +Function: bitwise_neg + + Inputs: + + Outputs: + + Purpose: bitwise negation + bitwise operations only make sense on native objects, hence the + largest object size should be the largest available c++ integer + size (currently long long) + +\*******************************************************************/ + +mp_integer bitwise_neg(const mp_integer &a) +{ + ullong_t result=~a.to_ulong(); + return result; +} + +/*******************************************************************\ + +Function: arith_left_shift + + Inputs: + + Outputs: + + Purpose: arithmetic left shift + bitwise operations only make sense on native objects, hence the + largest object size should be the largest available c++ integer + size (currently long long) + +\*******************************************************************/ + +mp_integer arith_left_shift( + const mp_integer &a, + const mp_integer &b, + std::size_t true_size) +{ + ullong_t shift=b.to_ulong(); + if(shift>true_size && a!=mp_integer(0)) + throw "shift value out of range"; + + ullong_t result=a.to_ulong()<true_size) + throw "shift value out of range"; + + ullong_t sign=(1<<(true_size-1))&number; + ullong_t pad=(sign==0) ? 0 : ~((1<<(true_size-shift))-1); + ullong_t result=(number>>shift)|pad; + return result; +} + +/*******************************************************************\ + +Function: logic_left_shift + + Inputs: + + Outputs: + + Purpose: logic left shift + bitwise operations only make sense on native objects, hence the + largest object size should be the largest available c++ integer + size (currently long long) + +\*******************************************************************/ + +mp_integer logic_left_shift( + const mp_integer &a, + const mp_integer &b, + std::size_t true_size) +{ + ullong_t shift=b.to_ulong(); + if(shift>true_size && a!=mp_integer(0)) + throw "shift value out of range"; + + ullong_t result=a.to_ulong()<true_size) + throw "shift value out of range"; + + ullong_t result=a.to_ulong()>>shift; + return result; +} + +/*******************************************************************\ + +Function: rotate_right + + Inputs: + + Outputs: + + Purpose: rotates right (MSB=LSB) + bitwise operations only make sense on native objects, hence the + largest object size should be the largest available c++ integer + size (currently long long) + +\*******************************************************************/ + +mp_integer rotate_right( + const mp_integer &a, + const mp_integer &b, + std::size_t true_size) +{ + ullong_t number=a.to_ulong(); + ullong_t shift=b.to_ulong(); + if(shift>true_size) + throw "shift value out of range"; + + ullong_t revShift=true_size-shift; + ullong_t filter=1<<(true_size-1); + ullong_t result=(number>>shift)|((number<true_size) + throw "shift value out of range"; + + ullong_t revShift=true_size-shift; + ullong_t filter=1<<(true_size-1); + ullong_t result=((number<>revShift); + return result; +} diff --git a/src/util/mp_arith.h b/src/util/mp_arith.h index 030a292bb74..046b1bff788 100644 --- a/src/util/mp_arith.h +++ b/src/util/mp_arith.h @@ -20,6 +20,28 @@ typedef BigInt mp_integer; std::ostream &operator<<(std::ostream &, const mp_integer &); mp_integer operator>>(const mp_integer &, const mp_integer &); mp_integer operator<<(const mp_integer &, const mp_integer &); +mp_integer bitwise_or(const mp_integer &, const mp_integer &); +mp_integer bitwise_and(const mp_integer &, const mp_integer &); +mp_integer bitwise_xor(const mp_integer &, const mp_integer &); +mp_integer bitwise_neg(const mp_integer &); + +mp_integer arith_left_shift( + const mp_integer &, const mp_integer &, std::size_t true_size); + +mp_integer arith_right_shift( + const mp_integer &, const mp_integer &, std::size_t true_size); + +mp_integer logic_left_shift( + const mp_integer &, const mp_integer &, std::size_t true_size); + +mp_integer logic_right_shift( + const mp_integer &, const mp_integer &, std::size_t true_size); + +mp_integer rotate_right( + const mp_integer &, const mp_integer &, std::size_t true_size); + +mp_integer rotate_left( + const mp_integer &, const mp_integer &, std::size_t true_size); const std::string integer2string(const mp_integer &, unsigned base=10); const mp_integer string2integer(const std::string &, unsigned base=10); @@ -28,5 +50,6 @@ const mp_integer binary2integer(const std::string &, bool is_signed); mp_integer::ullong_t integer2ulong(const mp_integer &); std::size_t integer2size_t(const mp_integer &); unsigned integer2unsigned(const mp_integer &); +const mp_integer mp_zero=string2integer("0"); #endif // CPROVER_UTIL_MP_ARITH_H From d81dd759c9373a526e35d900a6651fda0799c650 Mon Sep 17 00:00:00 2001 From: Dario Cattaruzza Date: Tue, 25 Oct 2016 16:18:08 +0100 Subject: [PATCH 044/699] Auxiliary function to retrieve tail of trace and added dead command to trace --- src/goto-programs/goto_trace.cpp | 5 ++++- src/goto-programs/goto_trace.h | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/goto-programs/goto_trace.cpp b/src/goto-programs/goto_trace.cpp index ad8bdcdfdd9..4179afb5395 100644 --- a/src/goto-programs/goto_trace.cpp +++ b/src/goto-programs/goto_trace.cpp @@ -65,6 +65,7 @@ void goto_trace_stept::output( case goto_trace_stept::ASSIGNMENT: out << "ASSIGNMENT"; break; case goto_trace_stept::GOTO: out << "GOTO"; break; case goto_trace_stept::DECL: out << "DECL"; break; + case goto_trace_stept::DEAD: out << "DEAD"; break; case goto_trace_stept::OUTPUT: out << "OUTPUT"; break; case goto_trace_stept::INPUT: out << "INPUT"; break; case goto_trace_stept::ATOMIC_BEGIN: out << "ATOMC_BEGIN"; break; @@ -73,7 +74,9 @@ void goto_trace_stept::output( case goto_trace_stept::SHARED_WRITE: out << "SHARED WRITE"; break; case goto_trace_stept::FUNCTION_CALL: out << "FUNCTION CALL"; break; case goto_trace_stept::FUNCTION_RETURN: out << "FUNCTION RETURN"; break; - default: assert(false); + default: + out << "unknown type: " << type << std::endl; + assert(false); } if(type==ASSERT || type==ASSUME || type==GOTO) diff --git a/src/goto-programs/goto_trace.h b/src/goto-programs/goto_trace.h index 507d538ada0..a669fac5e6b 100644 --- a/src/goto-programs/goto_trace.h +++ b/src/goto-programs/goto_trace.h @@ -154,6 +154,13 @@ class goto_tracet steps.push_back(step); } + // retrieves the final step in the trace for manipulation + // (used to fill a trace from code, hence non-const) + inline goto_trace_stept &get_last_step() + { + return steps.back(); + } + // delete all steps after (not including) s void trim_after(stepst::iterator s) { From 7fb8174485d59e458097725cc79947f42b08ad7b Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 13 Jan 2017 14:36:01 +0000 Subject: [PATCH 045/699] Fix arithmetic shift operators to_ulong() will negate a negative number, rather than returning its two's complement representation as an unsigned type as we might reasonably suppose. Instead use to_long() everywhere to preserve the bitwise representation and then use sign-bit filling to make sure the value is correctly re-encoded as mp_integer. --- src/util/mp_arith.cpp | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/util/mp_arith.cpp b/src/util/mp_arith.cpp index e70c654bd14..6a9082b6823 100644 --- a/src/util/mp_arith.cpp +++ b/src/util/mp_arith.cpp @@ -18,7 +18,8 @@ Author: Daniel Kroening, kroening@kroening.com #include "arith_tools.h" -typedef BigInt::ullong_t ullong_t; +typedef BigInt::ullong_t ullong_t; // NOLINT(readability/identifiers) +typedef BigInt::llong_t llong_t; // NOLINT(readability/identifiers) /*******************************************************************\ @@ -432,8 +433,12 @@ mp_integer arith_left_shift( if(shift>true_size && a!=mp_integer(0)) throw "shift value out of range"; - ullong_t result=a.to_ulong()<true_size) throw "shift value out of range"; - ullong_t sign=(1<<(true_size-1))&number; - ullong_t pad=(sign==0) ? 0 : ~((1<<(true_size-shift))-1); - ullong_t result=(number>>shift)|pad; + llong_t sign=(1<<(true_size-1))&number; + llong_t pad=(sign==0) ? 0 : ~((1<<(true_size-shift))-1); + llong_t result=(number >> shift)|pad; return result; } @@ -490,8 +495,17 @@ mp_integer logic_left_shift( ullong_t shift=b.to_ulong(); if(shift>true_size && a!=mp_integer(0)) throw "shift value out of range"; - - ullong_t result=a.to_ulong()<true_size) throw "shift value out of range"; - ullong_t result=a.to_ulong()>>shift; + ullong_t result=((ullong_t)a.to_long()) >> shift; return result; } @@ -550,7 +564,7 @@ mp_integer rotate_right( ullong_t revShift=true_size-shift; ullong_t filter=1<<(true_size-1); - ullong_t result=(number>>shift)|((number<> shift)|((number<>revShift); + ullong_t result=((number<> revShift); return result; } From fb616c542cec51cf99c61350e9d2df404eed700a Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 16 Jan 2017 14:58:46 +0000 Subject: [PATCH 046/699] Added a new class for handling the internals This code was originally in the `dump_ct` class but it is useful in other places (specifically when generating stubs we don't want to include any of these). --- src/goto-programs/Makefile | 5 +- src/goto-programs/system_library_symbols.cpp | 298 +++++++++++++++++++ src/goto-programs/system_library_symbols.h | 37 +++ 3 files changed, 339 insertions(+), 1 deletion(-) create mode 100644 src/goto-programs/system_library_symbols.cpp create mode 100644 src/goto-programs/system_library_symbols.h diff --git a/src/goto-programs/Makefile b/src/goto-programs/Makefile index d8cb835e4a8..485bc211e24 100644 --- a/src/goto-programs/Makefile +++ b/src/goto-programs/Makefile @@ -20,7 +20,10 @@ SRC = goto_convert.cpp goto_convert_function_call.cpp \ slice_global_inits.cpp goto_inline_class.cpp class_identifier.cpp \ show_goto_functions_json.cpp \ show_goto_functions_xml.cpp \ - remove_static_init_loops.cpp remove_instanceof.cpp + remove_static_init_loops.cpp \ + remove_instanceof.cpp \ + system_library_symbols.cpp \ + INCLUDES= -I .. diff --git a/src/goto-programs/system_library_symbols.cpp b/src/goto-programs/system_library_symbols.cpp new file mode 100644 index 00000000000..44bb1b1b2cd --- /dev/null +++ b/src/goto-programs/system_library_symbols.cpp @@ -0,0 +1,298 @@ +/*******************************************************************\ + +Module: Goto Programs + +Author: Thomas Kiley + +\*******************************************************************/ + +#include "system_library_symbols.h" +#include +#include +#include + +system_library_symbolst::system_library_symbolst() +{ + init_system_library_map(); +} + +/*******************************************************************\ + +Function: system_library_symbolst::init_system_library_map + +Inputs: + +Outputs: + +Purpose: To generate a map of header file names -> list of symbols + The symbol names are reserved as the header and source files + will be compiled in to the goto program. + +\*******************************************************************/ + +void system_library_symbolst::init_system_library_map() +{ + // ctype.h + std::list ctype_syms= + { + "isalnum", "isalpha", "isblank", "iscntrl", "isdigit", "isgraph", + "islower", "isprint", "ispunct", "isspace", "isupper", "isxdigit", + "tolower", "toupper" + }; + add_to_system_library("ctype.h", ctype_syms); + + // fcntl.h + std::list fcntl_syms= + { + "creat", "fcntl", "open" + }; + add_to_system_library("fcntl.h", fcntl_syms); + + // locale.h + std::list locale_syms= + { + "setlocale" + }; + add_to_system_library("locale.h", locale_syms); + + // math.h + std::list math_syms= + { + "acos", "acosh", "asin", "asinh", "atan", "atan2", "atanh", + "cbrt", "ceil", "copysign", "cos", "cosh", "erf", "erfc", "exp", + "exp2", "expm1", "fabs", "fdim", "floor", "fma", "fmax", "fmin", + "fmod", "fpclassify", "frexp", "hypot", "ilogb", "isfinite", + "isinf", "isnan", "isnormal", "j0", "j1", "jn", "ldexp", "lgamma", + "llrint", "llround", "log", "log10", "log1p", "log2", "logb", + "lrint", "lround", "modf", "nan", "nearbyint", "nextafter", "pow", + "remainder", "remquo", "rint", "round", "scalbln", "scalbn", + "signbit", "sin", "sinh", "sqrt", "tan", "tanh", "tgamma", + "trunc", "y0", "y1", "yn" + }; + add_to_system_library("math.h", math_syms); + + // pthread.h + std::list pthread_syms= + { + "pthread_cleanup_pop", "pthread_cleanup_push", + "pthread_cond_broadcast", "pthread_cond_destroy", + "pthread_cond_init", "pthread_cond_signal", + "pthread_cond_timedwait", "pthread_cond_wait", "pthread_create", + "pthread_detach", "pthread_equal", "pthread_exit", + "pthread_getspecific", "pthread_join", "pthread_key_delete", + "pthread_mutex_destroy", "pthread_mutex_init", + "pthread_mutex_lock", "pthread_mutex_trylock", + "pthread_mutex_unlock", "pthread_once", "pthread_rwlock_destroy", + "pthread_rwlock_init", "pthread_rwlock_rdlock", + "pthread_rwlock_unlock", "pthread_rwlock_wrlock", + "pthread_rwlockattr_destroy", "pthread_rwlockattr_getpshared", + "pthread_rwlockattr_init", "pthread_rwlockattr_setpshared", + "pthread_self", "pthread_setspecific" + }; + add_to_system_library("pthread.h", pthread_syms); + + // setjmp.h + std::list setjmp_syms= + { + "_longjmp", "_setjmp", "longjmp", "longjmperror", "setjmp", + "siglongjmp", "sigsetjmp" + }; + add_to_system_library("setjmp.h", setjmp_syms); + + // stdio.h + std::list stdio_syms= + { + "asprintf", "clearerr", "fclose", "fdopen", "feof", "ferror", + "fflush", "fgetc", "fgetln", "fgetpos", "fgets", "fgetwc", + "fgetws", "fileno", "fopen", "fprintf", "fpurge", "fputc", + "fputs", "fputwc", "fputws", "fread", "freopen", "fropen", + "fscanf", "fseek", "fsetpos", "ftell", "funopen", "fwide", + "fwopen", "fwprintf", "fwrite", "getc", "getchar", "getdelim", + "getline", "gets", "getw", "getwc", "getwchar", "mkdtemp", + "mkstemp", "mktemp", "perror", "printf", "putc", "putchar", + "puts", "putw", "putwc", "putwchar", "remove", "rewind", "scanf", + "setbuf", "setbuffer", "setlinebuf", "setvbuf", "snprintf", + "sprintf", "sscanf", "strerror", "swprintf", "sys_errlist", + "sys_nerr", "tempnam", "tmpfile", "tmpnam", "ungetc", "ungetwc", + "vasprintf", "vfprintf", "vfscanf", "vfwprintf", "vprintf", + "vscanf", "vsnprintf", "vsprintf", "vsscanf", "vswprintf", + "vwprintf", "wprintf", + /* non-public struct types */ + "tag-__sFILE", "tag-__sbuf", // OS X + "tag-_IO_FILE", "tag-_IO_marker", // Linux + }; + add_to_system_library("stdio.h", stdio_syms); + + // stdlib.h + std::list stdlib_syms= + { + "abort", "abs", "atexit", "atof", "atoi", "atol", "atoll", + "bsearch", "calloc", "div", "exit", "free", "getenv", "labs", + "ldiv", "llabs", "lldiv", "malloc", "mblen", "mbstowcs", "mbtowc", + "qsort", "rand", "realloc", "srand", "strtod", "strtof", "strtol", + "strtold", "strtoll", "strtoul", "strtoull", "system", "wcstombs", + "wctomb" + }; + add_to_system_library("stdlib.h", stdlib_syms); + + // string.h + std::list string_syms= + { + "strcat", "strncat", "strchr", "strrchr", "strcmp", "strncmp", + "strcpy", "strncpy", "strerror", "strlen", "strpbrk", "strspn", + "strcspn", "strstr", "strtok" + }; + add_to_system_library("string.h", string_syms); + + // time.h + std::list time_syms= + { + "asctime", "asctime_r", "ctime", "ctime_r", "difftime", "gmtime", + "gmtime_r", "localtime", "localtime_r", "mktime", + /* non-public struct types */ + "tag-timespec", "tag-timeval" + }; + add_to_system_library("time.h", time_syms); + + // unistd.h + std::list unistd_syms= + { + "_exit", "access", "alarm", "chdir", "chown", "close", "dup", + "dup2", "execl", "execle", "execlp", "execv", "execve", "execvp", + "fork", "fpathconf", "getcwd", "getegid", "geteuid", "getgid", + "getgroups", "getlogin", "getpgrp", "getpid", "getppid", "getuid", + "isatty", "link", "lseek", "pathconf", "pause", "pipe", "read", + "rmdir", "setgid", "setpgid", "setsid", "setuid", "sleep", + "sysconf", "tcgetpgrp", "tcsetpgrp", "ttyname", "ttyname_r", + "unlink", "write" + }; + add_to_system_library("unistd.h", unistd_syms); + + // sys/select.h + std::list sys_select_syms= + { + "select" + }; + add_to_system_library("sys/select.h", sys_select_syms); + + // sys/socket.h + std::list sys_socket_syms= + { + "accept", "bind", "connect" + }; + add_to_system_library("sys/socket.h", sys_socket_syms); + + // sys/stat.h + std::list sys_stat_syms= + { + "fstat", "lstat", "stat" + }; + add_to_system_library("sys/stat.h", sys_stat_syms); + +#if 0 + // sys/types.h + std::list sys_types_syms= + { + }; + add_to_system_library("sys/types.h", sys_types_syms); +#endif + + // sys/wait.h + std::list sys_wait_syms= + { + "wait", "waitpid" + }; + add_to_system_library("sys/wait.h", sys_wait_syms); +} + +/*******************************************************************\ + +Function: system_library_symbolst::add_to_system_library + +Inputs: + header_file - the name of the header file the symbol came from + symbols - a list of the names of the symbols in the header file + +Outputs: + +Purpose: To add the symbols from a specific header file to the + system library map. The symbol is used as the key so that + we can easily look up symbols. + +\*******************************************************************/ + +void system_library_symbolst::add_to_system_library( + irep_idt header_file, + std::list symbols) +{ + for(const irep_idt &symbol : symbols) + { + system_library_map[symbol]=header_file; + } +} + + +/*******************************************************************\ + +Function: system_library_symbolst::is_symbol_internal_symbol + +Inputs: + symbol - the symbol to check + +Outputs: True if the symbol is an internal symbol. If specific system + headers need to be included, the out_system_headers will contain + the headers. + +Purpose: To find out if a symbol is an internal symbol. + +\*******************************************************************/ + +bool system_library_symbolst::is_symbol_internal_symbol( + const symbolt &symbol, + std::set &out_system_headers) const +{ + const std::string &name_str=id2string(symbol.name); + + if(has_prefix(name_str, CPROVER_PREFIX) || + name_str=="__func__" || + name_str=="__FUNCTION__" || + name_str=="__PRETTY_FUNCTION__" || + name_str=="argc'" || + name_str=="argv'" || + name_str=="envp'" || + name_str=="envp_size'") + return true; + + const std::string &file_str=id2string(symbol.location.get_file()); + + // don't dump internal GCC builtins + if((file_str=="gcc_builtin_headers_alpha.h" || + file_str=="gcc_builtin_headers_arm.h" || + file_str=="gcc_builtin_headers_ia32.h" || + file_str=="gcc_builtin_headers_mips.h" || + file_str=="gcc_builtin_headers_power.h" || + file_str=="gcc_builtin_headers_generic.h") && + has_prefix(name_str, "__builtin_")) + return true; + + if(name_str=="__builtin_va_start" || + name_str=="__builtin_va_end" || + symbol.name==ID_gcc_builtin_va_arg) + { + out_system_headers.insert("stdarg.h"); + return true; + } + + if(name_str.find("$link")!=std::string::npos) + return false; + + const auto &it=system_library_map.find(symbol.name); + + if(it!=system_library_map.end()) + { + out_system_headers.insert(it->second); + return true; + } + + return false; +} diff --git a/src/goto-programs/system_library_symbols.h b/src/goto-programs/system_library_symbols.h new file mode 100644 index 00000000000..a253b903bd8 --- /dev/null +++ b/src/goto-programs/system_library_symbols.h @@ -0,0 +1,37 @@ +/*******************************************************************\ + +Module: Goto Programs + +Author: Thomas Kiley + +\*******************************************************************/ + +#ifndef CPROVER_GOTO_PROGRAMS_SYSTEM_LIBRARY_SYMBOLS_H +#define CPROVER_GOTO_PROGRAMS_SYSTEM_LIBRARY_SYMBOLS_H + +#include +#include +#include + +class symbolt; + +class system_library_symbolst +{ +public: + system_library_symbolst(); + + bool is_symbol_internal_symbol( + const symbolt &symbol, + std::set &out_system_headers) const; + +private: + void init_system_library_map(); + + void add_to_system_library( + irep_idt header_file, + std::list symbols); + + std::map system_library_map; +}; + +#endif // CPROVER_GOTO_PROGRAMS_SYSTEM_LIBRARY_SYMBOLS_H From fc756f336c04a788487c2f7e59bd1c8568c4c5f5 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 16 Jan 2017 17:07:04 +0000 Subject: [PATCH 047/699] Adding more symbols that should be excluded The existing symbols were missing a few symbols from the files they were supposed to be symbols for. Further, for some reason the math functions were sometimes used with a double underscore prefix. Some included files were missed (fenv.h, errno.c, noop.c). There were some other prefixes that clearly have internal meaning (__VERIFIER, nondet_). Also asserts weren't being included. These problems were discovered by running the make and seeing which tests failed and what functions were being stubbed. It is therefore not necessarily exhaustive. Perhaps there is a better approach to this problem. --- src/goto-programs/system_library_symbols.cpp | 71 +++++++++++++++++--- 1 file changed, 63 insertions(+), 8 deletions(-) diff --git a/src/goto-programs/system_library_symbols.cpp b/src/goto-programs/system_library_symbols.cpp index 44bb1b1b2cd..76023d0c455 100644 --- a/src/goto-programs/system_library_symbols.cpp +++ b/src/goto-programs/system_library_symbols.cpp @@ -10,6 +10,7 @@ Author: Thomas Kiley #include #include #include +#include system_library_symbolst::system_library_symbolst() { @@ -61,16 +62,28 @@ void system_library_symbolst::init_system_library_map() "acos", "acosh", "asin", "asinh", "atan", "atan2", "atanh", "cbrt", "ceil", "copysign", "cos", "cosh", "erf", "erfc", "exp", "exp2", "expm1", "fabs", "fdim", "floor", "fma", "fmax", "fmin", - "fmod", "fpclassify", "frexp", "hypot", "ilogb", "isfinite", - "isinf", "isnan", "isnormal", "j0", "j1", "jn", "ldexp", "lgamma", - "llrint", "llround", "log", "log10", "log1p", "log2", "logb", - "lrint", "lround", "modf", "nan", "nearbyint", "nextafter", "pow", - "remainder", "remquo", "rint", "round", "scalbln", "scalbn", - "signbit", "sin", "sinh", "sqrt", "tan", "tanh", "tgamma", - "trunc", "y0", "y1", "yn" + "fmod", "fpclassify", "fpclassifyl", "fpclassifyf", "frexp", + "hypot", "ilogb", "isfinite", "isinf", "isnan", "isnormal", + "j0", "j1", "jn", "ldexp", "lgamma", "llrint", "llround", "log", + "log10", "log1p", "log2", "logb", "lrint", "lround", "modf", "nan", + "nearbyint", "nextafter", "pow", "remainder", "remquo", "rint", + "round", "scalbln", "scalbn", "signbit", "sin", "sinh", "sqrt", + "tan", "tanh", "tgamma", "trunc", "y0", "y1", "yn", "isinff", + "isinfl", "isnanf", "isnanl" }; add_to_system_library("math.h", math_syms); + // for some reason the math functions can sometimes be prefixed with + // a double underscore + std::list underscore_math_syms; + for(const irep_idt &math_sym : math_syms) + { + std::ostringstream underscore_id; + underscore_id << "__" << math_sym; + underscore_math_syms.push_back(irep_idt(underscore_id.str())); + } + add_to_system_library("math.h", underscore_math_syms); + // pthread.h std::list pthread_syms= { @@ -140,7 +153,8 @@ void system_library_symbolst::init_system_library_map() { "strcat", "strncat", "strchr", "strrchr", "strcmp", "strncmp", "strcpy", "strncpy", "strerror", "strlen", "strpbrk", "strspn", - "strcspn", "strstr", "strtok" + "strcspn", "strstr", "strtok", "strcasecmp", "strncasecmp", "strdup", + "memset" }; add_to_system_library("string.h", string_syms); @@ -189,6 +203,27 @@ void system_library_symbolst::init_system_library_map() }; add_to_system_library("sys/stat.h", sys_stat_syms); + std::list fenv_syms= + { + "fenv_t", "fexcept_t", "feclearexcept", "fegetexceptflag", + "feraiseexcept", "fesetexceptflag", "fetestexcept", + "fegetround", "fesetround", "fegetenv", "feholdexcept", + "fesetenv", "feupdateenv" + }; + add_to_system_library("fenv.h", fenv_syms); + + std::list errno_syms= + { + "__error", "__errno_location", "__errno" + }; + add_to_system_library("errno.c", errno_syms); + + std::list noop_syms= + { + "__noop" + }; + add_to_system_library("noop.c", noop_syms); + #if 0 // sys/types.h std::list sys_types_syms= @@ -263,6 +298,17 @@ bool system_library_symbolst::is_symbol_internal_symbol( name_str=="envp_size'") return true; + // exclude nondet instructions + if(has_prefix(name_str, "nondet_")) + { + return true; + } + + if(has_prefix(name_str, "__VERIFIER")) + { + return true; + } + const std::string &file_str=id2string(symbol.location.get_file()); // don't dump internal GCC builtins @@ -283,6 +329,15 @@ bool system_library_symbolst::is_symbol_internal_symbol( return true; } + // don't dump asserts + else if(name_str=="__assert_fail" || + name_str=="_assert" || + name_str=="__assert_c99" || + name_str=="_wassert") + { + return true; + } + if(name_str.find("$link")!=std::string::npos) return false; From 2f5b86689fb7aabd189ce038633c51a5f410dcd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vojt=C4=9Bch=20Forejt?= Date: Fri, 20 Jan 2017 21:51:10 +0000 Subject: [PATCH 048/699] Autocomplete script for bash See documentation in scripts/bash-autocomplete/Readme.md --- scripts/bash-autocomplete/.gitignore | 1 + scripts/bash-autocomplete/Readme.md | 31 ++++++++++++ scripts/bash-autocomplete/cbmc.sh.template | 43 +++++++++++++++++ scripts/bash-autocomplete/extract_switches.sh | 48 +++++++++++++++++++ .../switch_extractor_helper.c | 3 ++ 5 files changed, 126 insertions(+) create mode 100644 scripts/bash-autocomplete/.gitignore create mode 100644 scripts/bash-autocomplete/Readme.md create mode 100644 scripts/bash-autocomplete/cbmc.sh.template create mode 100755 scripts/bash-autocomplete/extract_switches.sh create mode 100644 scripts/bash-autocomplete/switch_extractor_helper.c diff --git a/scripts/bash-autocomplete/.gitignore b/scripts/bash-autocomplete/.gitignore new file mode 100644 index 00000000000..1e0acedc4f2 --- /dev/null +++ b/scripts/bash-autocomplete/.gitignore @@ -0,0 +1 @@ +cbmc.sh diff --git a/scripts/bash-autocomplete/Readme.md b/scripts/bash-autocomplete/Readme.md new file mode 100644 index 00000000000..00101d99159 --- /dev/null +++ b/scripts/bash-autocomplete/Readme.md @@ -0,0 +1,31 @@ +# CBMC Autocomplete Scripts for Bash +This directory contains an autocomplete script for bash. +## Installation +1. Compile cbmc and + +2. `cd scripts/bash-autocomplete` + +3. `./extract-switches.sh` + +4. Put the following at the end of you in your `~/.bashrc`, with the directories adapted to your directory structure: + ```bash + cbmcautocomplete=~/diffblue/cbmc/scripts/bash-autocomplete/cbmc.sh + if [ -f $cbmcautocomplete ]; then + . $cbmcautocomplete + fi + ``` +## Usage +As with the usual autocomplete in bash, start typing a switch to complete it, for example: +``` +cbmc --clas +``` +will complete to +``` +cbmc --classpath +``` + +## Features implemented + +* Completing all switches +* Completing values for `--cover`, `--mm` and `--arch` +* When completing a name of a file to analyze, only files with supported extensions are shown. diff --git a/scripts/bash-autocomplete/cbmc.sh.template b/scripts/bash-autocomplete/cbmc.sh.template new file mode 100644 index 00000000000..cbd64762b2d --- /dev/null +++ b/scripts/bash-autocomplete/cbmc.sh.template @@ -0,0 +1,43 @@ +#!/bin/bash +_cbmc_autocomplete() +{ + #list of all switches cbmc has. IMPORTANT: in the template file, this variable must be defined on line 5. + local switches="" + #word on which the cursor is + local cur=${COMP_WORDS[COMP_CWORD]} + #previous word (in case it is a switch with a parameter) + local prev=${COMP_WORDS[COMP_CWORD-1]} + + #check if the command before cursor is a switch that takes parameters, if yes, + #offer a choice of parameters + case "$prev" in + --cover) #for coverage we list the options explicitly + COMPREPLY=( $( compgen -W "assertion path branch location decision condition mcdc cover" -- $cur ) ) + return 0 + ;; + --mm) #for memory models we list the options explicitly + COMPREPLY=( $( compgen -W "sc tso pso" -- $cur ) ) + return 0 + ;; + --arch) #for architecture we list the options explicitly + COMPREPLY=( $( compgen -W "i386 x86_64" -- $cur ) ) + return 0 + ;; + -I|--classpath|-cp|--outfile|--existing-coverage|--graphml-cex) + #a switch that takes a file parameter of which we don't know an extension + #TODO probably we can do more for -I, --classpath, -cp + _filedir + return 0 + ;; + esac + + #complete a switch from a standard list, if the parameter under cursor starts with a hyphen + if [[ "$cur" == -* ]]; then + COMPREPLY=( $( compgen -W "$switches" -- $cur ) ) + return 0 + fi + + #if none of the above applies, offer directories and files that we can analyze + _filedir "@(class|jar|cpp|cc|c\+\+|ii|cxx|c|i|gb)" +} +complete -F _cbmc_autocomplete cbmc diff --git a/scripts/bash-autocomplete/extract_switches.sh b/scripts/bash-autocomplete/extract_switches.sh new file mode 100755 index 00000000000..e000b469bea --- /dev/null +++ b/scripts/bash-autocomplete/extract_switches.sh @@ -0,0 +1,48 @@ +#!/bin/bash +echo "Compiling the helper file to extract the raw list of parameters from cbmc" +g++ -c -MMD -MP -std=c++11 -Wall -I ../../src/ -ftrack-macro-expansion=0 -fno-diagnostics-show-caret switch_extractor_helper.c -o tmp.o 2> pragma.txt + +retval=$? + +#clean up compiled files, we don't need them. +rm tmp.o 2> /dev/null +rm tmp.d 2> /dev/null + +#check if compilation went fine +if [ $retval -ne 0 ]; then + echo "Problem compiling the helper file, parameter list not extracted." + exit 1; +fi + +echo "Converting the raw parameter list to the format required by autocomplete scripts" +rawstring=`sed "s/^.*pragma message: \(.*\)/\1/" pragma.txt` +#delete pragma file, we won't need it +rm pragma.txt 2> /dev/null + +#now the main bit, convert from raw format to a proper list of switches +cleanstring=`( + #extract 2-hyphen switches, such as --foo + #grep for '(foo)' expressions, and then use sed to remove parantheses and put '--' at the start + (echo $rawstring | grep -o "([^)]*)" | sed "s/^.\(.*\).$/--\1/") ; + #extract 1-hyphen switches, such as -F + #use sed to remove all (foo) expressions, then you're left with switches and ':', so grep the colons out and then use sed to include the '-' + (echo $rawstring | sed "s/([^)]*)//g" | grep -o "[a-zA-Z0-9]" | sed "s/\(.*\)/-\1/") + ) | tr '\n' ' '` + +#sanity check that there is only one line of output +if [ `echo $cleanstring | wc -l | awk '{print $1}'` -ne 1 ]; then + echo "Problem converting the parameter list to the correct format, I was expecting one line but either got 0 or >2. This is likely to be an error in this conversion script." + exit 1; +fi + +#sanity check that there are no dangerous characters +echo $cleanstring | grep -q "[^a-zA-Z0-9 -]" +if [ $? -eq 0 ]; then + echo "Problem converting the parameter list to the correct format, illegal characters detected. This is likely to be an error in this conversion script." + exit 1; +fi + +echo "Injecting the parameter list to the autocomplete file." +sed "5 s/.*/ local switches=\"$cleanstring\"/" cbmc.sh.template > cbmc.sh + +rm pragma.txt 2> /dev/null diff --git a/scripts/bash-autocomplete/switch_extractor_helper.c b/scripts/bash-autocomplete/switch_extractor_helper.c new file mode 100644 index 00000000000..4d9cc2e56fe --- /dev/null +++ b/scripts/bash-autocomplete/switch_extractor_helper.c @@ -0,0 +1,3 @@ +#include "cbmc/cbmc_parse_options.h" + +#pragma message CBMC_OPTIONS From d485c88a2cc9bc72dcafcee97da98cadb73f4961 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 25 Jan 2017 15:11:44 +0000 Subject: [PATCH 049/699] Factor class identifier extraction out of remove virtuals This will be useful for other passes that inspect an object's dynamic clsid, such as the forthcoming lower-instanceof pass. --- src/goto-programs/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/goto-programs/Makefile b/src/goto-programs/Makefile index 485bc211e24..8b69282c381 100644 --- a/src/goto-programs/Makefile +++ b/src/goto-programs/Makefile @@ -22,6 +22,7 @@ SRC = goto_convert.cpp goto_convert_function_call.cpp \ show_goto_functions_xml.cpp \ remove_static_init_loops.cpp \ remove_instanceof.cpp \ + class_identifier.cpp \ system_library_symbols.cpp \ From 99eb1a0b3df91439d8fb635ceadacfe68b1e9c76 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 24 Jan 2017 13:32:11 +0000 Subject: [PATCH 050/699] Discover lexical scopes for anonymous variables This enables tight variable scoping even when Java debug information is not available, which helps with analyses that benefit from DEAD instructions keeping their domains as small as possible. --- .../java_bytecode_convert_method.cpp | 37 +++++++++++++++++++ .../java_bytecode_convert_method_class.h | 4 ++ 2 files changed, 41 insertions(+) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index f101d19c824..dda893544bc 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -804,6 +804,43 @@ static void gather_symbol_live_ranges( /*******************************************************************\ +Function: java_bytecode_convert_methodt::check_static_field_stub + + Inputs: `se`: Symbol expression referring to a static field + `basename`: The static field's basename + + Outputs: Creates a symbol table entry for the static field if one + doesn't exist already. + + Purpose: See above + +\*******************************************************************/ + +void java_bytecode_convert_methodt::check_static_field_stub( + const symbol_exprt &symbol_expr, + const irep_idt &basename) +{ + const auto &id=symbol_expr.get_identifier(); + if(symbol_table.symbols.find(id)==symbol_table.symbols.end()) + { + // Create a stub, to be overwritten if/when the real class is loaded. + symbolt new_symbol; + new_symbol.is_static_lifetime=true; + new_symbol.is_lvalue=true; + new_symbol.is_state_var=true; + new_symbol.name=id; + new_symbol.base_name=basename; + new_symbol.type=symbol_expr.type(); + new_symbol.pretty_name=new_symbol.name; + new_symbol.mode=ID_java; + new_symbol.is_type=false; + new_symbol.value.make_nil(); + symbol_table.add(new_symbol); + } +} + +/*******************************************************************\ + Function: java_bytecode_convert_methodt::convert_instructions Inputs: diff --git a/src/java_bytecode/java_bytecode_convert_method_class.h b/src/java_bytecode/java_bytecode_convert_method_class.h index ae4ba711640..6844e337f22 100644 --- a/src/java_bytecode/java_bytecode_convert_method_class.h +++ b/src/java_bytecode/java_bytecode_convert_method_class.h @@ -219,6 +219,10 @@ class java_bytecode_convert_methodt:public messaget const code_typet &); const bytecode_infot &get_bytecode_info(const irep_idt &statement); + + void check_static_field_stub( + const symbol_exprt &se, + const irep_idt &basename); }; #endif From 7ac505d22314729638c7ef40c121cb7872e2150b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Sat, 21 Jan 2017 00:42:53 +0100 Subject: [PATCH 051/699] loop unwinding in static init of Java enum Static initialization of Java enums sometimes contains extra code that loops over the array of enum elements. This often prevents initialization of the enumeration and leads to zero coverage. This patch counts the number of enum elements, and explicitely unwinds all loops in to this number + 1. This acts as a heuristic to make static inits of enums finish. --- src/util/irep_ids.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/irep_ids.txt b/src/util/irep_ids.txt index 9bcb7807671..5ada8981c19 100644 --- a/src/util/irep_ids.txt +++ b/src/util/irep_ids.txt @@ -737,6 +737,7 @@ bswap java_bytecode_index java_instanceof java_super_method_call +skip_initialize java_enum_static_unwind string_constraint string_not_contains_constraint From 0cf34af4dcb60170b2c753d3aae5ac33e120dfe1 Mon Sep 17 00:00:00 2001 From: Cristina Date: Thu, 9 Feb 2017 15:36:36 +0000 Subject: [PATCH 052/699] Support for Java assume --- src/Makefile | 10 +++++++++- .../java_bytecode_convert_method.cpp | 20 ++++++++++++++++++- .../library/src/org/cprover/CProver.java | 11 ++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 src/java_bytecode/library/src/org/cprover/CProver.java diff --git a/src/Makefile b/src/Makefile index 269ddeda140..e4c62f33eed 100644 --- a/src/Makefile +++ b/src/Makefile @@ -108,4 +108,12 @@ libzip-build: @echo "Building libzip" @(cd ../libzip; BASE=`pwd`; ./configure --with-zlib=$(BASE)/zlib ; make) -.PHONY: minisat2-download glucose-download zlib-download libzip-download libzip-build +cprover-jar-build: + @echo "Building org.cprover.jar" + @(cd java_bytecode/library/; \ + mkdir -p target; \ + javac -d target/ `find src/ -name "*.java"`; \ + cd target; jar cf org.cprover.jar `find . -name "*.class"`; \ + mv org.cprover.jar ../../../) + +.PHONY: minisat2-download glucose-download zlib-download libzip-download libzip-build cprover-jar-build diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index dda893544bc..447b5dacb80 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -5,7 +5,6 @@ Module: JAVA Bytecode Language Conversion Author: Daniel Kroening, kroening@kroening.com \*******************************************************************/ - #ifdef DEBUG #include #endif @@ -1093,6 +1092,25 @@ codet java_bytecode_convert_methodt::convert_instructions( get_message_handler()); } } + // replace calls to CProver.assume + else if(statement=="invokestatic" && + id2string(arg0.get(ID_identifier))== + "java::org.cprover.CProver.assume:(Z)V") + { + const code_typet &code_type=to_code_type(arg0.type()); + // sanity check: function has the right number of args + assert(code_type.parameters().size()==1); + + exprt operand = pop(1)[0]; + // we may need to adjust the type of the argument + if(operand.type()!=bool_typet()) + operand.make_typecast(bool_typet()); + + c=code_assumet(operand); + source_locationt loc=i_it->source_location; + loc.set_function(method_id); + c.add_source_location()=loc; + } else if(statement=="invokeinterface" || statement=="invokespecial" || statement=="invokevirtual" || diff --git a/src/java_bytecode/library/src/org/cprover/CProver.java b/src/java_bytecode/library/src/org/cprover/CProver.java new file mode 100644 index 00000000000..72c3eeb1d70 --- /dev/null +++ b/src/java_bytecode/library/src/org/cprover/CProver.java @@ -0,0 +1,11 @@ +package org.cprover; + +public final class CProver +{ + public static boolean enableAssume=true; + public static void assume(boolean condition) + { + if(enableAssume) + throw new RuntimeException("Cannot execute program with CProver.assume()"); + } +} From 1436e39606ad256052d19eb874a26db101663552 Mon Sep 17 00:00:00 2001 From: Cristina Date: Thu, 9 Feb 2017 19:16:01 +0000 Subject: [PATCH 053/699] Regression tests for Java assume --- regression/cbmc-java/assume1/Assume1.class | Bin 0 -> 660 bytes regression/cbmc-java/assume1/Assume1.java | 10 ++++++++++ regression/cbmc-java/assume1/test.desc | 8 ++++++++ regression/cbmc-java/assume2/Assume2.class | Bin 0 -> 661 bytes regression/cbmc-java/assume2/Assume2.java | 10 ++++++++++ regression/cbmc-java/assume2/test.desc | 8 ++++++++ regression/cbmc-java/assume3/Assume3.class | Bin 0 -> 684 bytes regression/cbmc-java/assume3/Assume3.java | 10 ++++++++++ regression/cbmc-java/assume3/test.desc | 8 ++++++++ 9 files changed, 54 insertions(+) create mode 100644 regression/cbmc-java/assume1/Assume1.class create mode 100644 regression/cbmc-java/assume1/Assume1.java create mode 100644 regression/cbmc-java/assume1/test.desc create mode 100644 regression/cbmc-java/assume2/Assume2.class create mode 100644 regression/cbmc-java/assume2/Assume2.java create mode 100644 regression/cbmc-java/assume2/test.desc create mode 100644 regression/cbmc-java/assume3/Assume3.class create mode 100644 regression/cbmc-java/assume3/Assume3.java create mode 100644 regression/cbmc-java/assume3/test.desc diff --git a/regression/cbmc-java/assume1/Assume1.class b/regression/cbmc-java/assume1/Assume1.class new file mode 100644 index 0000000000000000000000000000000000000000..b9a49bc9971d81889935e4cefba60fffd292840c GIT binary patch literal 660 zcmZWmO>fgc5PcIn-o!OcnwAp6M*}U8a==3BjS3Y7kSc`_sZ}L%K-xIlvc=6-Yp3G3 zRN{uj8IULf3GVzT#H_KJ1Bda<&b)c^X8ill_n!bZupXj@PKYbGT1S9u0@p+M=m@NY z=;DUJO~T@u%ra$jZ6?`coyk$E#snG?f=xZq`9p%&Ti+x2eKS^s#z0Th^Xbt@*7KOOz00JZztI_?K6sR6(<62N0n_Xo!!*5Z$42kiwh0$@a+$n+CXdU$+GdiL zW5XRYwTXJF-H@o{xpyc}WP~|H0;>_$a4SL`A))OGaVjSVF+=|?^u$_Y38L&3xE_MCyTXUjp+<#ekzJV;{JJ~}gyD@9*r(7c}k5#6v8lMm4h4LvE z_-aGGa=`xppk~|2fJNYCk`r@=WkFXJv2CWPzIoh1@<+xu*ezL z{F>3O*6jozApDQ;y>F;|hIfia=RM|rz<+gy>MzIZ6}3); + assert x>0; + } +} diff --git a/regression/cbmc-java/assume1/test.desc b/regression/cbmc-java/assume1/test.desc new file mode 100644 index 00000000000..1f80a1c1e86 --- /dev/null +++ b/regression/cbmc-java/assume1/test.desc @@ -0,0 +1,8 @@ +CORE +Assume1.class +--function Assume1.foo +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/cbmc-java/assume2/Assume2.class b/regression/cbmc-java/assume2/Assume2.class new file mode 100644 index 0000000000000000000000000000000000000000..36e09875d7d72406f27d2512b116cd7a586871d6 GIT binary patch literal 661 zcmZWmO>fgc5PcIn-qzUno^WK~BuixK(09eCnga*11F5qH_0G9+VNAS@VxDw$i zdIHx7iz_nEl`XWH<_~o)$C;WCXhaCs^;8%430{A7hu{y)L=l=pJylO<`(tId9hlG_ znp9>x(rS0F9{u9A&I#f0L7va{)!lnc^U4^e>2EqVddp{%aAvEJ>6<6=pz3R^r&%Q% zZJC)()nn~M;)>_ao;;K><`4^9kFkOqF+xOyjw>XYobDzJ{X5VjYmFs{s#oAy0JN~cv4J)g`NcKA zWVEaGy1{!0{{wvQD{7zM9ii0~?=bfr{)=POe>!5XB%Uwz1-CcYTlkMa4`;E&xMe;8 pyl{h-7<2B#=~^iTEVP3!5J#2XXL$d+b`*8g;te-jhc7jp{{vk5b}Ik? literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/assume2/Assume2.java b/regression/cbmc-java/assume2/Assume2.java new file mode 100644 index 00000000000..6991167bfb8 --- /dev/null +++ b/regression/cbmc-java/assume2/Assume2.java @@ -0,0 +1,10 @@ +import org.cprover.CProver; + +class Assume2 +{ + static void foo(int x) + { + CProver.assume(x>3); + assert x>4; + } +} diff --git a/regression/cbmc-java/assume2/test.desc b/regression/cbmc-java/assume2/test.desc new file mode 100644 index 00000000000..35a954116f8 --- /dev/null +++ b/regression/cbmc-java/assume2/test.desc @@ -0,0 +1,8 @@ +CORE +Assume2.class +--function Assume2.foo +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/cbmc-java/assume3/Assume3.class b/regression/cbmc-java/assume3/Assume3.class new file mode 100644 index 0000000000000000000000000000000000000000..916ad4065fb77e04ba492a6f7499799ea22c85f7 GIT binary patch literal 684 zcmZuvO>fgc5PcIn-qjFF61OtQv!_%-mcDc`H0~3xAqC{AfGBid#E$Dx0p|qd2PXj?l4be zx-X5k>w42I-|B+k51$mpVy+(UaD%zj8DYKuW_T!%Wt_@v7LQ7!v)N8HK$;m-qW_c$ z=SHPW-o21Vb^q3GlGgHqQNA#VdakXQu%7q8jtH@WP~dimP236LBOvsavl;rw_%ma2 zLl8Ar;BJU}=o30i@XN`eN=lZOn^~M3nfzFpc<`!!rOU4pOeM?WroX zQPZ=bY^YptflqhLx8dVCzK834g7dFP%Wt9)KDJhRylCLkZyo7^Z2$lO literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/assume3/Assume3.java b/regression/cbmc-java/assume3/Assume3.java new file mode 100644 index 00000000000..895deee9ca0 --- /dev/null +++ b/regression/cbmc-java/assume3/Assume3.java @@ -0,0 +1,10 @@ +import org.cprover.CProver; + +class Assume3 +{ + public static void main(String[] args) + { + CProver.assume(false); + assert false; + } +} diff --git a/regression/cbmc-java/assume3/test.desc b/regression/cbmc-java/assume3/test.desc new file mode 100644 index 00000000000..0ad8c00399f --- /dev/null +++ b/regression/cbmc-java/assume3/test.desc @@ -0,0 +1,8 @@ +CORE +Assume3.class + +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring From 5c309076a390ff8993ece33466f8b65005c14c4d Mon Sep 17 00:00:00 2001 From: Cristina Date: Tue, 20 Sep 2016 14:47:20 +0100 Subject: [PATCH 054/699] Remove assume as coverage target --- src/goto-instrument/cover.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index fa92bc27cc7..991f91b75b7 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -35,7 +35,12 @@ class basic_blockst source_location_map[block_count]=it->source_location; next_is_target= +#if 0 + // Disabled for being too messy it->is_goto() || it->is_function_call() || it->is_assume(); +#else + it->is_goto() || it->is_function_call(); +#endif } } From e55f20b6f30656881f80090f098937206704d262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Wed, 1 Feb 2017 16:05:54 +0100 Subject: [PATCH 055/699] output covered lines as CSV in show_properties --- src/goto-instrument/cover.cpp | 56 ++++++++++++++++++++++----- src/goto-programs/show_properties.cpp | 3 ++ src/util/irep_ids.txt | 3 +- src/util/source_location.h | 10 +++++ 4 files changed, 62 insertions(+), 10 deletions(-) diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index 991f91b75b7..489ee44eb5e 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -10,8 +10,10 @@ Date: May 2016 #include #include +#include #include +#include #include "cover.h" @@ -28,6 +30,11 @@ class basic_blockst if(next_is_target || it->is_target()) block_count++; + const irep_idt &line=it->source_location.get_line(); + if(!line.empty()) + block_line_cover_map[block_count] + .insert(unsafe_string2unsigned(id2string(line))); + block_map[it]=block_count; if(!it->source_location.is_nil() && @@ -42,6 +49,24 @@ class basic_blockst it->is_goto() || it->is_function_call(); #endif } + + // create list of covered lines as CSV string and set as property of source + // location of basic block + for(const auto &cover_set : block_line_cover_map) + { + std::string covered_lines; + bool first=true; + for(const auto &line_number : cover_set.second) + { + if(first) + first=false; + else + covered_lines+=","; + covered_lines+=std::to_string(line_number); + } + source_location_map[cover_set.first] + .set_basic_block_covered_lines(covered_lines); + } } // map program locations to block numbers @@ -52,6 +77,11 @@ class basic_blockst typedef std::map source_location_mapt; source_location_mapt source_location_map; + // map block numbers to set of line numbers + typedef std::map > + block_line_cover_mapt; + block_line_cover_mapt block_line_cover_map; + inline unsigned operator[](goto_programt::const_targett t) { return block_map[t]; @@ -419,7 +449,7 @@ std::set collect_mcdc_controlling_nested( const std::set &decisions) { // To obtain the 1st-level controlling conditions - std::set controlling = collect_mcdc_controlling(decisions); + std::set controlling=collect_mcdc_controlling(decisions); std::set result; // For each controlling condition, to check if it contains @@ -632,7 +662,7 @@ void remove_repetition(std::set &exprs) **/ for(auto &y : new_exprs) { - bool iden = true; + bool iden=true; for(auto &c : conditions) { std::set signs1=sign_of_expr(c, x); @@ -674,7 +704,7 @@ void remove_repetition(std::set &exprs) } // update the original ''exprs'' - exprs = new_exprs; + exprs=new_exprs; } /*******************************************************************\ @@ -843,7 +873,8 @@ bool is_mcdc_pair( if(diff_count==1) return true; - else return false; + else + return false; } /*******************************************************************\ @@ -968,7 +999,8 @@ void minimize_mcdc_controlling( { controlling=new_controlling; } - else break; + else + break; } } @@ -1302,9 +1334,12 @@ void instrument_cover_goals( const std::set decisions=collect_decisions(i_it); std::set both; - std::set_union(conditions.begin(), conditions.end(), - decisions.begin(), decisions.end(), - inserter(both, both.end())); + std::set_union( + conditions.begin(), + conditions.end(), + decisions.begin(), + decisions.end(), + inserter(both, both.end())); const source_locationt source_location=i_it->source_location; @@ -1402,6 +1437,9 @@ void instrument_cover_goals( f_it->first=="__CPROVER_initialize") continue; - instrument_cover_goals(symbol_table, f_it->second.body, criterion); + instrument_cover_goals( + symbol_table, + f_it->second.body, + criterion); } } diff --git a/src/goto-programs/show_properties.cpp b/src/goto-programs/show_properties.cpp index c7a6bdedf3f..edde459b933 100644 --- a/src/goto-programs/show_properties.cpp +++ b/src/goto-programs/show_properties.cpp @@ -130,6 +130,9 @@ void show_properties_json( json_properties.push_back(jsont()).make_object(); json_property["name"]=json_stringt(id2string(property_id)); json_property["class"]=json_stringt(id2string(property_class)); + if(!source_location.get_basic_block_covered_lines().empty()) + json_property["covered_lines"]= + json_stringt(id2string(source_location.get_basic_block_covered_lines())); json_property["sourceLocation"]=json(source_location); json_property["description"]=json_stringt(id2string(description)); json_property["expression"]= diff --git a/src/util/irep_ids.txt b/src/util/irep_ids.txt index 5ada8981c19..29907f11040 100644 --- a/src/util/irep_ids.txt +++ b/src/util/irep_ids.txt @@ -801,4 +801,5 @@ cprover_string_to_char_array_func cprover_string_to_lower_case_func cprover_string_to_upper_case_func cprover_string_trim_func -cprover_string_value_of_func \ No newline at end of file +cprover_string_value_of_func +basic_block_covered_lines \ No newline at end of file diff --git a/src/util/source_location.h b/src/util/source_location.h index b24befcb8c4..9d905c775cb 100644 --- a/src/util/source_location.h +++ b/src/util/source_location.h @@ -73,6 +73,11 @@ class source_locationt:public irept return get(ID_java_bytecode_index); } + const irep_idt &get_basic_block_covered_lines() const + { + return get(ID_basic_block_covered_lines); + } + void set_file(const irep_idt &file) { set(ID_file, file); @@ -128,6 +133,11 @@ class source_locationt:public irept set(ID_java_bytecode_index, index); } + void set_basic_block_covered_lines(const irep_idt &covered_lines) + { + return set(ID_basic_block_covered_lines, covered_lines); + } + void set_hide() { set(ID_hide, true); From 2ae1f47f3a3a5e0af15b022205df3f4942792a88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Mon, 13 Feb 2017 15:59:29 +0100 Subject: [PATCH 056/699] compress list of lines into line ranges --- src/goto-instrument/cover.cpp | 19 ++--- src/goto-programs/show_properties.cpp | 5 +- src/util/Makefile | 2 +- src/util/format_number_range.cpp | 114 ++++++++++++++++++++++++++ src/util/format_number_range.h | 21 +++++ 5 files changed, 147 insertions(+), 14 deletions(-) create mode 100644 src/util/format_number_range.cpp create mode 100644 src/util/format_number_range.h diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index 489ee44eb5e..9f1aa347679 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -12,6 +12,7 @@ Date: May 2016 #include #include +#include #include #include @@ -51,19 +52,15 @@ class basic_blockst } // create list of covered lines as CSV string and set as property of source - // location of basic block + // location of basic block, compress to ranges if applicable + format_number_ranget format_lines; for(const auto &cover_set : block_line_cover_map) { - std::string covered_lines; - bool first=true; - for(const auto &line_number : cover_set.second) - { - if(first) - first=false; - else - covered_lines+=","; - covered_lines+=std::to_string(line_number); - } + assert(!cover_set.second.empty()); + std::vector + line_list{cover_set.second.begin(), cover_set.second.end()}; + + std::string covered_lines=format_lines(line_list); source_location_map[cover_set.first] .set_basic_block_covered_lines(covered_lines); } diff --git a/src/goto-programs/show_properties.cpp b/src/goto-programs/show_properties.cpp index edde459b933..cbbb00225c7 100644 --- a/src/goto-programs/show_properties.cpp +++ b/src/goto-programs/show_properties.cpp @@ -131,8 +131,9 @@ void show_properties_json( json_property["name"]=json_stringt(id2string(property_id)); json_property["class"]=json_stringt(id2string(property_class)); if(!source_location.get_basic_block_covered_lines().empty()) - json_property["covered_lines"]= - json_stringt(id2string(source_location.get_basic_block_covered_lines())); + json_property["coveredLines"]= + json_stringt( + id2string(source_location.get_basic_block_covered_lines())); json_property["sourceLocation"]=json(source_location); json_property["description"]=json_stringt(id2string(description)); json_property["expression"]= diff --git a/src/util/Makefile b/src/util/Makefile index 6cc42a18fb8..c605d26c747 100644 --- a/src/util/Makefile +++ b/src/util/Makefile @@ -22,7 +22,7 @@ SRC = arith_tools.cpp base_type.cpp cmdline.cpp config.cpp symbol_table.cpp \ irep_ids.cpp byte_operators.cpp string2int.cpp file_util.cpp \ memory_info.cpp pipe_stream.cpp irep_hash.cpp endianness_map.cpp \ ssa_expr.cpp json_irep.cpp json_expr.cpp \ - string_utils.cpp + format_number_range.cpp string_utils.cpp INCLUDES= -I .. diff --git a/src/util/format_number_range.cpp b/src/util/format_number_range.cpp new file mode 100644 index 00000000000..146808118ce --- /dev/null +++ b/src/util/format_number_range.cpp @@ -0,0 +1,114 @@ +/*******************************************************************\ + +Module: Format vector of numbers into a compressed range + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#include +#include + +#include "format_number_range.h" + +/*******************************************************************\ + +Function: format_number_range::operator() + + Inputs: vector of numbers + + Outputs: string of compressed number range representation + + Purpose: create shorter representation for output + +\*******************************************************************/ + +std::string format_number_ranget::operator()(std::vector &numbers) +{ + std::string number_range; + std::sort(numbers.begin(), numbers.end()); + unsigned end_number=numbers.back(); + if(numbers.front()==end_number) + number_range=std::to_string(end_number); // only single number + else + { + bool next=true; + bool first=true; + bool range=false; + unsigned start_number=numbers.front(); + unsigned last_number=start_number; + + for(const auto &number : numbers) + { + if(next) + { + next=false; + start_number=number; + last_number=number; + } + // advance one forward + else + { + if(number==last_number+1 && !(number==end_number)) + { + last_number++; + if(last_number>start_number+1) + range=true; + } + // end this block range + else + { + if(first) + first=false; + else + number_range+=","; + if(last_number>start_number) + { + if(range) + { + if(number==end_number && number==last_number+1) + number_range+= + std::to_string(start_number)+"-"+std::to_string(end_number); + else if(number==end_number) + number_range+= + std::to_string(start_number)+"-"+std::to_string(last_number)+ + ","+std::to_string(end_number); + else + number_range+= + std::to_string(start_number)+"-"+std::to_string(last_number); + } + else + { + if(number!=end_number) + number_range+= + std::to_string(start_number)+","+std::to_string(last_number); + else + number_range+= + std::to_string(start_number)+","+std::to_string(last_number)+ + std::to_string(end_number); + } + start_number=number; + last_number=number; + range=false; + continue; + } + else + { + if(number!=end_number) + number_range+=std::to_string(start_number); + else + number_range+=std::to_string(start_number)+","+ + std::to_string(end_number); + start_number=number; + last_number=number; + range=false; + continue; // already set next start number + } + next=true; + } + } + } + } + assert(!number_range.empty()); + return number_range; +} diff --git a/src/util/format_number_range.h b/src/util/format_number_range.h new file mode 100644 index 00000000000..7ff016e9c4d --- /dev/null +++ b/src/util/format_number_range.h @@ -0,0 +1,21 @@ +/*******************************************************************\ + +Module: Format vector of numbers into a compressed range + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#ifndef CPROVER_UTIL_FORMAT_NUMBER_RANGE_H +#define CPROVER_UTIL_FORMAT_NUMBER_RANGE_H + +#include +#include + +class format_number_ranget +{ +public: + std::string operator()(std::vector &); +}; + +#endif // CPROVER_UTIL_FORMAT_NUMBER_RANGE_H From f5f47a7043bf3389d41ca2a0628f58ec9b3670e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Wed, 15 Feb 2017 23:53:28 +0100 Subject: [PATCH 057/699] add regression test for coverage lines --- regression/cbmc-java/covered1/covered1.class | Bin 0 -> 750 bytes regression/cbmc-java/covered1/covered1.java | 37 +++++++++++++++++++ regression/cbmc-java/covered1/test.desc | 19 ++++++++++ 3 files changed, 56 insertions(+) create mode 100644 regression/cbmc-java/covered1/covered1.class create mode 100644 regression/cbmc-java/covered1/covered1.java create mode 100644 regression/cbmc-java/covered1/test.desc diff --git a/regression/cbmc-java/covered1/covered1.class b/regression/cbmc-java/covered1/covered1.class new file mode 100644 index 0000000000000000000000000000000000000000..7cb91496b7df5bc0b1e7f8b6db0aa9a4992bd947 GIT binary patch literal 750 zcmYk4TWb?h6ouEBOJ*jSCQa%+wf9SU)TC(>1*uXHiUBVVl?py}G8x*`n3Rwf?N9N^ zw?5lA2nzlHf0VlRp`r}?+xwiuIcx3B{QULp2Y?11WKlpRKptxXEx04NE4U}93TlFN zL0zyR*c3E8G(Fr`Q12Nn#s|ikf_1jeB4V@^>_Ml)>WysI1sj4*K||0~$ZU1{-O*zO zx6*2@?I}1<2AxEq@T}WUUYxvZC&O1!yT_f0-BA?3eI6Z~HT4zzt+;o2-LA;x?C#)X z7$-Yjb0Hp_Cc~stuO3CGQHU8VhnPe$L`g6uxGA_LC<|^2t_rRRt_ZHw`A%h|$M8{-GG5hkKSyRDeikN*$m^Iy)OhYEqlR2ll zS<@b~#hAe?6y{ichs_Uot-nHPCxxZm6t>Q!aHMjj%4jczr~MSZE>9n(2$=R$Wc3#W z Date: Fri, 17 Feb 2017 11:12:48 +0100 Subject: [PATCH 058/699] fix problem with missing comma / range fix for reaching end --- src/util/format_number_range.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/util/format_number_range.cpp b/src/util/format_number_range.cpp index 146808118ce..cca3bbf154c 100644 --- a/src/util/format_number_range.cpp +++ b/src/util/format_number_range.cpp @@ -8,6 +8,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include #include "format_number_range.h" @@ -83,9 +84,16 @@ std::string format_number_ranget::operator()(std::vector &numbers) number_range+= std::to_string(start_number)+","+std::to_string(last_number); else - number_range+= - std::to_string(start_number)+","+std::to_string(last_number)+ - std::to_string(end_number); + { + if(start_number+1==last_number && last_number+1==number) + number_range+= + std::to_string(start_number)+"-"+std::to_string(end_number); + else + number_range+= + std::to_string(start_number)+ + ","+std::to_string(last_number)+ + ","+std::to_string(end_number); + } } start_number=number; last_number=number; From b7d828bc18cf807c8b4c649f676e6945d2d9633f Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 16 Jan 2017 15:11:43 +0000 Subject: [PATCH 059/699] Updated dump-C to use the new class --- src/goto-instrument/dump_c.cpp | 260 +------------------ src/goto-instrument/dump_c_class.h | 11 +- src/goto-programs/system_library_symbols.cpp | 4 +- src/goto-programs/system_library_symbols.h | 3 +- 4 files changed, 11 insertions(+), 267 deletions(-) diff --git a/src/goto-instrument/dump_c.cpp b/src/goto-instrument/dump_c.cpp index d06a79e01d8..24005138109 100644 --- a/src/goto-instrument/dump_c.cpp +++ b/src/goto-instrument/dump_c.cpp @@ -163,7 +163,8 @@ void dump_ct::operator()(std::ostream &os) } // we don't want to dump in full all definitions - if(!tag_added && ignore(symbol)) + if(!tag_added && + system_symbols.is_symbol_internal_symbol(symbol, system_headers)) continue; if(!symbols_sorted.insert(name_str).second) @@ -344,7 +345,7 @@ void dump_ct::convert_compound( ns.lookup(to_symbol_type(type).get_identifier()); assert(symbol.is_type); - if(!ignore(symbol)) + if(!system_symbols.is_symbol_internal_symbol(symbol, system_headers)) convert_compound(symbol.type, unresolved, recursive, os); } else if(type.id()==ID_c_enum_tag) @@ -353,7 +354,7 @@ void dump_ct::convert_compound( ns.lookup(to_c_enum_tag_type(type).get_identifier()); assert(symbol.is_type); - if(!ignore(symbol)) + if(!system_symbols.is_symbol_internal_symbol(symbol, system_headers)) convert_compound(symbol.type, unresolved, recursive, os); } else if(type.id()==ID_array || type.id()==ID_pointer) @@ -610,259 +611,6 @@ void dump_ct::convert_compound_enum( /*******************************************************************\ -Function: dump_ct::init_system_library_map - -Inputs: - -Outputs: - -Purpose: - -\*******************************************************************/ - -#define ADD_TO_SYSTEM_LIBRARY(v, header) \ - for(size_t i=0; isecond); - return true; - } - - return false; -} - -/*******************************************************************\ - Function: dump_ct::cleanup_decl Inputs: diff --git a/src/goto-instrument/dump_c_class.h b/src/goto-instrument/dump_c_class.h index 6bb7b79638e..c8c77da5102 100644 --- a/src/goto-instrument/dump_c_class.h +++ b/src/goto-instrument/dump_c_class.h @@ -15,6 +15,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include class dump_ct { @@ -30,7 +31,7 @@ class dump_ct language(factory()) { if(use_system_headers) - init_system_library_map(); + system_symbols=system_library_symbolst(); } virtual ~dump_ct() @@ -51,21 +52,15 @@ class dump_ct std::set system_headers; - typedef std::unordered_map - system_library_mapt; - system_library_mapt system_library_map; + system_library_symbolst system_symbols; typedef std::unordered_map declared_enum_constants_mapt; declared_enum_constants_mapt declared_enum_constants; - void init_system_library_map(); - std::string type_to_string(const typet &type); std::string expr_to_string(const exprt &expr); - bool ignore(const symbolt &symbol); - static std::string indent(const unsigned n) { return std::string(2*n, ' '); diff --git a/src/goto-programs/system_library_symbols.cpp b/src/goto-programs/system_library_symbols.cpp index 76023d0c455..250eb3b1cdb 100644 --- a/src/goto-programs/system_library_symbols.cpp +++ b/src/goto-programs/system_library_symbols.cpp @@ -284,7 +284,7 @@ Purpose: To find out if a symbol is an internal symbol. bool system_library_symbolst::is_symbol_internal_symbol( const symbolt &symbol, - std::set &out_system_headers) const + std::set &out_system_headers) const { const std::string &name_str=id2string(symbol.name); @@ -345,7 +345,7 @@ bool system_library_symbolst::is_symbol_internal_symbol( if(it!=system_library_map.end()) { - out_system_headers.insert(it->second); + out_system_headers.insert(id2string(it->second)); return true; } diff --git a/src/goto-programs/system_library_symbols.h b/src/goto-programs/system_library_symbols.h index a253b903bd8..9438e052a76 100644 --- a/src/goto-programs/system_library_symbols.h +++ b/src/goto-programs/system_library_symbols.h @@ -11,6 +11,7 @@ Author: Thomas Kiley #include #include +#include #include class symbolt; @@ -22,7 +23,7 @@ class system_library_symbolst bool is_symbol_internal_symbol( const symbolt &symbol, - std::set &out_system_headers) const; + std::set &out_system_headers) const; private: void init_system_library_map(); From fef1fed6b8c7894243d652396f185179cfb985a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Thu, 2 Mar 2017 15:10:22 +0100 Subject: [PATCH 060/699] update interpreter --- .../goto_instrument_parse_options.cpp | 2 +- src/goto-programs/interpreter.cpp | 864 ++++++++++++++++-- src/goto-programs/interpreter.h | 5 +- src/goto-programs/interpreter_class.h | 157 +++- src/goto-programs/interpreter_evaluate.cpp | 798 ++++++++++++++-- 5 files changed, 1649 insertions(+), 177 deletions(-) diff --git a/src/goto-instrument/goto_instrument_parse_options.cpp b/src/goto-instrument/goto_instrument_parse_options.cpp index 3cbbac3a55b..cce5aaad42b 100644 --- a/src/goto-instrument/goto_instrument_parse_options.cpp +++ b/src/goto-instrument/goto_instrument_parse_options.cpp @@ -561,7 +561,7 @@ int goto_instrument_parse_optionst::doit() if(cmdline.isset("interpreter")) { status() << "Starting interpreter" << eom; - interpreter(symbol_table, goto_functions); + interpreter(symbol_table, goto_functions, get_message_handler()); return 0; } diff --git a/src/goto-programs/interpreter.cpp b/src/goto-programs/interpreter.cpp index 2b4841a7c22..8d1565db914 100644 --- a/src/goto-programs/interpreter.cpp +++ b/src/goto-programs/interpreter.cpp @@ -9,13 +9,23 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include #include +#include #include #include +#include +#include +#include +#include +#include #include "interpreter.h" #include "interpreter_class.h" +#include "remove_returns.h" + +const size_t interpretert::npos=std::numeric_limits::max(); /*******************************************************************\ @@ -30,9 +40,46 @@ Function: interpretert::operator() \*******************************************************************/ void interpretert::operator()() +{ + status() << "0- Initialize:" << eom; + initialize(true); + try + { + status() << "Type h for help\n" << eom; + + while(!done) + command(); + + status() << total_steps << "- Program End.\n" << eom; + } + catch (const char *e) + { + error() << e << "\n" << eom; + } + + while(!done) + command(); +} + +/*******************************************************************\ + +Function: interpretert::initialize + + Inputs: + + Outputs: + + Purpose: Initializes the memory map of the interpreter and + [optionally] runs up to the entry point (thus doing + the cprover initialization) + +\*******************************************************************/ + +void interpretert::initialize(bool init) { build_memory_map(); + total_steps=0; const goto_functionst::function_mapt::const_iterator main_it=goto_functions.function_map.find(goto_functionst::entry_point()); @@ -44,17 +91,27 @@ void interpretert::operator()() if(!goto_function.body_available()) throw "main has no body"; - PC=goto_function.body.instructions.begin(); + pc=goto_function.body.instructions.begin(); function=main_it; done=false; - - while(!done) + if(init) { + stack_depth=call_stack.size()+1; show_state(); - command(); - if(!done) + step(); + while(!done && (stack_depth<=call_stack.size()) && (stack_depth!=npos)) + { + show_state(); + step(); + } + while(!done && (call_stack.size()==0)) + { + show_state(); step(); + } + clear_input_flags(); + input_vars.clear(); } } @@ -66,26 +123,31 @@ Function: interpretert::show_state Outputs: - Purpose: + Purpose: displays the current position of the pc and corresponding + code \*******************************************************************/ void interpretert::show_state() { - std::cout << std::endl; - std::cout << "----------------------------------------------------" - << std::endl; + if(!show) + return; + status() << "\n" + << total_steps+1 + << " ----------------------------------------------------\n"; - if(PC==function->second.body.instructions.end()) + if(pc==function->second.body.instructions.end()) { - std::cout << "End of function `" - << function->first << "'" << std::endl; + status() << "End of function `" << function->first << "'\n"; } else function->second.body.output_instruction( - ns, function->first, std::cout, PC); + ns, + function->first, + status(), + pc); - std::cout << std::endl; + status() << eom; } /*******************************************************************\ @@ -96,7 +158,7 @@ Function: interpretert::command Outputs: - Purpose: + Purpose: reads a user command and executes it. \*******************************************************************/ @@ -111,9 +173,97 @@ void interpretert::command() } char ch=tolower(command[0]); - if(ch=='q') done=true; + else if(ch=='h') + { + status() + << "Interpreter help\n" + << "h: display this menu\n" + << "j: output json trace\n" + << "m: output memory dump\n" + << "o: output goto trace\n" + << "q: quit\n" + << "r: run until completion\n" + << "s#: step a number of instructions\n" + << "sa: step across a function\n" + << "so: step out of a function\n" + << eom; + } + else if(ch=='j') + { + jsont json_steps; + convert(ns, steps, json_steps); + ch=tolower(command[1]); + if(ch==' ') + { + std::ofstream file; + file.open(command+2); + if(file.is_open()) + { + json_steps.output(file); + file.close(); + return; + } + } + json_steps.output(result()); + } + else if(ch=='m') + { + ch=tolower(command[1]); + print_memory(ch=='i'); + } + else if(ch=='o') + { + ch=tolower(command[1]); + if(ch==' ') + { + std::ofstream file; + file.open(command+2); + if(file.is_open()) + { + steps.output(ns, file); + file.close(); + return; + } + } + steps.output(ns, result()); + } + else if(ch=='r') + { + ch=tolower(command[1]); + initialize(ch!='0'); + } + else if((ch=='s') || (ch==0)) + { + num_steps=1; + stack_depth=npos; + ch=tolower(command[1]); + if(ch=='e') + num_steps=npos; + else if(ch=='o') + stack_depth=call_stack.size(); + else if(ch=='a') + stack_depth=call_stack.size()+1; + else + { + num_steps=atoi(command+1); + if(num_steps==0) + num_steps=1; + } + while(!done && ((num_steps==npos) || ((num_steps--)>0))) + { + step(); + show_state(); + } + while(!done && (stack_depth<=call_stack.size()) && (stack_depth!=npos)) + { + step(); + show_state(); + } + return; + } + show_state(); } /*******************************************************************\ @@ -124,41 +274,50 @@ Function: interpretert::step Outputs: - Purpose: + Purpose: executes a single step and updates the program counter \*******************************************************************/ void interpretert::step() { - if(PC==function->second.body.instructions.end()) + total_steps++; + if(pc==function->second.body.instructions.end()) { if(call_stack.empty()) done=true; else { - PC=call_stack.top().return_PC; + pc=call_stack.top().return_pc; function=call_stack.top().return_function; - stack_pointer=call_stack.top().old_stack_pointer; + // TODO: this increases memory size quite quickly. + // Should check alternatives call_stack.pop(); } return; } - next_PC=PC; - next_PC++; + next_pc=pc; + next_pc++; - switch(PC->type) + steps.add_step(goto_trace_stept()); + goto_trace_stept &trace_step=steps.get_last_step(); + trace_step.thread_nr=thread_id; + trace_step.pc=pc; + switch(pc->type) { case GOTO: + trace_step.type=goto_trace_stept::GOTO; execute_goto(); break; case ASSUME: + trace_step.type=goto_trace_stept::ASSUME; execute_assume(); break; case ASSERT: + trace_step.type=goto_trace_stept::ASSERT; execute_assert(); break; @@ -167,38 +326,46 @@ void interpretert::step() break; case DECL: + trace_step.type=goto_trace_stept::DECL; execute_decl(); break; case SKIP: case LOCATION: + trace_step.type=goto_trace_stept::LOCATION; + break; case END_FUNCTION: + trace_step.type=goto_trace_stept::FUNCTION_RETURN; break; case RETURN: + trace_step.type=goto_trace_stept::FUNCTION_RETURN; if(call_stack.empty()) throw "RETURN without call"; // NOLINT(readability/throw) - if(PC->code.operands().size()==1 && + if(pc->code.operands().size()==1 && call_stack.top().return_value_address!=0) { - std::vector rhs; - evaluate(PC->code.op0(), rhs); + mp_vectort rhs; + evaluate(pc->code.op0(), rhs); assign(call_stack.top().return_value_address, rhs); } - next_PC=function->second.body.instructions.end(); + next_pc=function->second.body.instructions.end(); break; case ASSIGN: + trace_step.type=goto_trace_stept::ASSIGNMENT; execute_assign(); break; case FUNCTION_CALL: + trace_step.type=goto_trace_stept::FUNCTION_CALL; execute_function_call(); break; case START_THREAD: + trace_step.type=goto_trace_stept::SPAWN; throw "START_THREAD not yet implemented"; // NOLINT(readability/throw) case END_THREAD: @@ -206,19 +373,44 @@ void interpretert::step() break; case ATOMIC_BEGIN: + trace_step.type=goto_trace_stept::ATOMIC_BEGIN; throw "ATOMIC_BEGIN not yet implemented"; // NOLINT(readability/throw) case ATOMIC_END: + trace_step.type=goto_trace_stept::ATOMIC_END; throw "ATOMIC_END not yet implemented"; // NOLINT(readability/throw) case DEAD: - throw "DEAD not yet implemented"; // NOLINT(readability/throw) - + trace_step.type=goto_trace_stept::DEAD; + break; + case THROW: + trace_step.type=goto_trace_stept::GOTO; + while(!done && (pc->type!=CATCH)) + { + if(pc==function->second.body.instructions.end()) + { + if(call_stack.empty()) + done=true; + else + { + pc=call_stack.top().return_pc; + function=call_stack.top().return_function; + call_stack.pop(); + } + } + else + { + next_pc=pc; + next_pc++; + } + } + break; + case CATCH: + break; default: throw "encountered instruction with undefined instruction type"; } - - PC=next_PC; + pc=next_pc; } /*******************************************************************\ @@ -229,21 +421,21 @@ Function: interpretert::execute_goto Outputs: - Purpose: + Purpose: executes a goto instruction \*******************************************************************/ void interpretert::execute_goto() { - if(evaluate_boolean(PC->guard)) + if(evaluate_boolean(pc->guard)) { - if(PC->targets.empty()) + if(pc->targets.empty()) throw "taken goto without target"; - if(PC->targets.size()>=2) + if(pc->targets.size()>=2) throw "non-deterministic goto encountered"; - next_PC=PC->targets.front(); + next_pc=pc->targets.front(); } } @@ -255,19 +447,37 @@ Function: interpretert::execute_other Outputs: - Purpose: + Purpose: executes side effects of 'other' instructions \*******************************************************************/ void interpretert::execute_other() { - const irep_idt &statement=PC->code.get_statement(); - + const irep_idt &statement=pc->code.get_statement(); if(statement==ID_expression) { - assert(PC->code.operands().size()==1); - std::vector rhs; - evaluate(PC->code.op0(), rhs); + assert(pc->code.operands().size()==1); + mp_vectort rhs; + evaluate(pc->code.op0(), rhs); + } + else if(statement==ID_array_set) + { + mp_vectort tmp, rhs; + evaluate(pc->code.op1(), tmp); + mp_integer address=evaluate_address(pc->code.op0()); + size_t size=get_size(pc->code.op0().type()); + while(rhs.size()code.get_statement()==ID_decl); + assert(pc->code.get_statement()==ID_decl); +} + +/*******************************************************************\ + +Function: interpretert::get_component_id + + Inputs: an object and a memory offset + + Outputs: + + Purpose: retrieves the member at offset + +\*******************************************************************/ + +irep_idt interpretert::get_component_id( + const irep_idt &object, + unsigned offset) +{ + const symbolt &symbol=ns.lookup(object); + const typet real_type=ns.follow(symbol.type); + if(real_type.id()!=ID_struct) + throw "request for member of non-struct"; + + const struct_typet &struct_type=to_struct_type(real_type); + const struct_typet::componentst &components=struct_type.components(); + for(struct_typet::componentst::const_iterator it=components.begin(); + it!=components.end(); it++) + { + if(offset<=0) + return it->id(); + size_t size=get_size(it->type()); + offset-=size; + } + return object; +} + +/*******************************************************************\ + +Function: interpretert::get_type + + Inputs: + + Outputs: + + Purpose: returns the type object corresponding to id + +\*******************************************************************/ + +typet interpretert::get_type(const irep_idt &id) const +{ + dynamic_typest::const_iterator it=dynamic_types.find(id); + if(it==dynamic_types.end()) + return symbol_table.lookup(id).type; + return it->second; +} + +/*******************************************************************\ + +Function: interpretert::get_value + + Inputs: + + Outputs: + + Purpose: retrives the constant value at memory location offset + as an object of type type + +\*******************************************************************/ + +exprt interpretert::get_value( + const typet &type, + std::size_t offset, + bool use_non_det) +{ + const typet real_type=ns.follow(type); + if(real_type.id()==ID_struct) + { + exprt result=struct_exprt(real_type); + const struct_typet &struct_type=to_struct_type(real_type); + const struct_typet::componentst &components=struct_type.components(); + + // Retrieve the values for the individual members + result.reserve_operands(components.size()); + for(struct_typet::componentst::const_iterator it=components.begin(); + it!=components.end(); it++) + { + size_t size=get_size(it->type()); + const exprt operand=get_value(it->type(), offset); + offset+=size; + result.copy_to_operands(operand); + } + return result; + } + else if(real_type.id()==ID_array) + { + // Get size of array + exprt result=array_exprt(to_array_type(real_type)); + const exprt &size_expr=static_cast(type.find(ID_size)); + size_t subtype_size=get_size(type.subtype()); + mp_integer mp_count; + to_integer(size_expr, mp_count); + unsigned count=integer2unsigned(mp_count); + + // Retrieve the value for each member in the array + result.reserve_operands(count); + for(unsigned i=0; i=0)) + return side_effect_expr_nondett(type); + mp_vectort rhs; + rhs.push_back(memory[offset].value); + return get_value(type, rhs); +} + +/*******************************************************************\ + + Function: interpretert::get_value + + Inputs: + + Outputs: + + Purpose: returns the value at offset in the form of type given a + memory buffer rhs which is typically a structured type + +\*******************************************************************/ + +exprt interpretert::get_value( + const typet &type, + mp_vectort &rhs, + std::size_t offset) +{ + const typet real_type=ns.follow(type); + assert(!rhs.empty()); + + if(real_type.id()==ID_struct) + { + exprt result=struct_exprt(real_type); + const struct_typet &struct_type=to_struct_type(real_type); + const struct_typet::componentst &components=struct_type.components(); + + // Retrieve the values for the individual members + result.reserve_operands(components.size()); + for(const struct_union_typet::componentt &expr : components) + { + size_t size=get_size(expr.type()); + const exprt operand=get_value(expr.type(), rhs, offset); + offset+=size; + result.copy_to_operands(operand); + } + return result; + } + else if(real_type.id()==ID_array) + { + exprt result(ID_constant, type); + const exprt &size_expr=static_cast(type.find(ID_size)); + + // Get size of array + size_t subtype_size=get_size(type.subtype()); + mp_integer mp_count; + to_integer(size_expr, mp_count); + unsigned count=integer2unsigned(mp_count); + + // Retrieve the value for each member in the array + result.reserve_operands(count); + for(unsigned i=0; i object count " << memory.size() << eom; + throw "interpreter: reading from invalid pointer"; + } + else if(real_type.id()==ID_string) + { + // Strings are currently encoded by their irep_idt ID. + return constant_exprt( + irep_idt(rhs[offset].to_long(), 0), + type); + } + // Retrieve value of basic data type + return from_integer(rhs[offset], type); } /*******************************************************************\ @@ -298,29 +754,56 @@ Function: interpretert::execute_assign Outputs: - Purpose: + Purpose: executes the assign statement at the current pc value \*******************************************************************/ void interpretert::execute_assign() { const code_assignt &code_assign= - to_code_assign(PC->code); + to_code_assign(pc->code); - std::vector rhs; + mp_vectort rhs; evaluate(code_assign.rhs(), rhs); if(!rhs.empty()) { mp_integer address=evaluate_address(code_assign.lhs()); - unsigned size=get_size(code_assign.lhs().type()); + size_t size=get_size(code_assign.lhs().type()); if(size!=rhs.size()) - std::cout << "!! failed to obtain rhs (" - << rhs.size() << " vs. " - << size << ")" << std::endl; + error() << "!! failed to obtain rhs (" + << rhs.size() << " vs. " + << size << ")\n" + << eom; else + { + goto_trace_stept &trace_step=steps.get_last_step(); assign(address, rhs); + trace_step.full_lhs=code_assign.lhs(); + + // TODO: need to look at other cases on ssa_exprt + // (dereference should be handled on ssa) + if(ssa_exprt::can_build_identifier(trace_step.full_lhs)) + { + trace_step.lhs_object=ssa_exprt(trace_step.full_lhs); + } + trace_step.full_lhs_value=get_value(trace_step.full_lhs.type(), rhs); + trace_step.lhs_object_value=trace_step.full_lhs_value; + } + } + else if(code_assign.rhs().id()==ID_side_effect) + { + side_effect_exprt side_effect=to_side_effect_expr(code_assign.rhs()); + if(side_effect.get_statement()==ID_nondet) + { + unsigned address=integer2unsigned(evaluate_address(code_assign.lhs())); + size_t size=get_size(code_assign.lhs().type()); + for(size_t i=0; i &rhs) + const mp_vectort &rhs) { - for(unsigned i=0; iguard)) + if(!evaluate_boolean(pc->guard)) throw "assumption failed"; } @@ -384,8 +875,14 @@ Function: interpretert::execute_assert void interpretert::execute_assert() { - if(!evaluate_boolean(PC->guard)) - throw "assertion failed"; + if(!evaluate_boolean(pc->guard)) + { + if((target_assert==pc) || stop_on_assertion) + throw "program assertion reached"; + else if(show) + error() << "assertion failed at " << pc->location_number + << "\n" << eom; + } } /*******************************************************************\ @@ -403,7 +900,7 @@ Function: interpretert::execute_function_call void interpretert::execute_function_call() { const code_function_callt &function_call= - to_code_function_call(PC->code); + to_code_function_call(pc->code); // function to be called mp_integer a=evaluate_address(function_call.function()); @@ -413,8 +910,12 @@ void interpretert::execute_function_call() else if(a>=memory.size()) throw "out-of-range function call"; + // Retrieve the empty last trace step struct we pushed for this step + // of the interpreter run to fill it with the corresponding data + goto_trace_stept &trace_step=steps.get_last_step(); const memory_cellt &cell=memory[integer2size_t(a)]; const irep_idt &identifier=cell.identifier; + trace_step.identifier=identifier; const goto_functionst::function_mapt::const_iterator f_it= goto_functions.function_map.find(identifier); @@ -432,7 +933,7 @@ void interpretert::execute_function_call() return_value_address=0; // values of the arguments - std::vector > argument_values; + std::vector argument_values; argument_values.resize(function_call.arguments().size()); @@ -446,7 +947,7 @@ void interpretert::execute_function_call() call_stack.push(stack_framet()); stack_framet &frame=call_stack.top(); - frame.return_PC=next_PC; + frame.return_pc=next_pc; frame.return_function=function; frame.old_stack_pointer=stack_pointer; frame.return_value_address=return_value_address; @@ -458,24 +959,7 @@ void interpretert::execute_function_call() for(const auto &id : locals) { const symbolt &symbol=ns.lookup(id); - unsigned size=get_size(symbol.type); - - if(size!=0) - { - frame.local_map[id]=stack_pointer; - - for(unsigned i=0; i=memory.size()) - memory.resize(address+1); - memory[address].value=0; - memory[address].identifier=id; - memory[address].offset=i; - } - - stack_pointer+=size; - } + frame.local_map[id]=integer2unsigned(build_memory_map(id, symbol.type)); } // assign the arguments @@ -485,7 +969,7 @@ void interpretert::execute_function_call() if(argument_values.size()second.body.instructions.begin(); + next_pc=f_it->second.body.instructions.begin(); } else - throw "no body for "+id2string(identifier); + { + list_input_varst::iterator it= + function_input_vars.find(function_call.function().get(ID_identifier)); + if(it!=function_input_vars.end()) + { + mp_vectort value; + assert(!it->second.empty()); + assert(!it->second.front().return_assignments.empty()); + evaluate(it->second.front().return_assignments.back().value, value); + if(return_value_address>0) + { + assign(return_value_address, value); + } + it->second.pop_front(); + return; + } + if(show) + error() << "no body for "+id2string(identifier) << eom; + } } /*******************************************************************\ @@ -510,7 +1012,7 @@ Function: interpretert::build_memory_map Outputs: - Purpose: + Purpose: Creates a memory map of all static symbols in the program \*******************************************************************/ @@ -520,6 +1022,10 @@ void interpretert::build_memory_map() memory.resize(1); memory[0].offset=0; memory[0].identifier="NULL-OBJECT"; + memory[0].initialized=0; + + num_dynamic_objects=0; + dynamic_types.clear(); // now do regular static symbols for(const auto &s : symbol_table.symbols) @@ -543,7 +1049,7 @@ Function: interpretert::build_memory_map void interpretert::build_memory_map(const symbolt &symbol) { - unsigned size=0; + size_t size=0; if(symbol.type.id()==ID_code) { @@ -560,29 +1066,120 @@ void interpretert::build_memory_map(const symbolt &symbol) memory.resize(address+size); memory_map[symbol.name]=address; - for(unsigned i=0; i(type.find(ID_size)); + mp_vectort computed_size; + evaluate(size_expr, computed_size); + if(computed_size.size()==1 && + computed_size[0]>=0) + { + result() << "Concretized array with size " << computed_size[0] + << eom; + return array_typet(type.subtype(), + constant_exprt::integer_constant(computed_size[0].to_ulong())); + } + else + { + error() << "Failed to concretize variable array" + << eom; + } + } + return type; +} + +/*******************************************************************\ + +Function: interpretert::build_memory_map + + Inputs: + + Outputs: Updtaes the memory map to include variable id if it does + not exist + + Purpose: Populates dynamic entries of the memory map + +\*******************************************************************/ + +mp_integer interpretert::build_memory_map( + const irep_idt &id, + const typet &type) +{ + typet alloc_type=concretize_type(type); + size_t size=get_size(alloc_type); + auto it=dynamic_types.find(id); + + if(it!=dynamic_types.end()) + { + unsigned offset=1; + unsigned address=memory_map[id]; + while(memory[address+offset].offset>0) offset++; + + // current size <= size already recorded + if(size<=offset) + return memory_map[id]; + } + + // The current size is bigger then the one previously recorded + // in the memory map + + if(size==0) + size=1; // This is a hack to create existence + + unsigned address=memory.size(); + memory.resize(address+size); + memory_map[id]=address; + dynamic_types.insert(std::pair(id, alloc_type)); + + for(size_t i=0; i(type.find(ID_size)); - unsigned subtype_size=get_size(type.subtype()); + size_t subtype_size=get_size(type.subtype()); - mp_integer i; - if(!to_integer(size_expr, i)) - return subtype_size*integer2unsigned(i); - else - return subtype_size; + mp_vectort i; + evaluate(size_expr, i); + if(i.size()==1) + { + // Go via the binary representation to reproduce any + // overflow behaviour. + exprt size_const=from_integer(i[0], size_expr.type()); + mp_integer size_mp; + assert(!to_integer(size_const, size_mp)); + return subtype_size*integer2unsigned(size_mp); + } + return subtype_size; } else if(type.id()==ID_symbol) { return get_size(ns.follow(type)); } + return 1; +} + +/******************************************************************* \ + +Function: interpretert::get_value + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +exprt interpretert::get_value(const irep_idt &id) +{ + // The dynamic type and the static symbol type may differ for VLAs, + // where the symbol carries a size expression and the dynamic type + // registry contains its actual length. + auto findit=dynamic_types.find(id); + typet get_type; + if(findit!=dynamic_types.end()) + get_type=findit->second; else - return 1; + get_type=symbol_table.lookup(id).type; + + symbol_exprt symbol_expr(id, get_type); + mp_integer whole_lhs_object_address=evaluate_address(symbol_expr); + + return get_value(get_type, integer2unsigned(whole_lhs_object_address)); } /*******************************************************************\ @@ -652,8 +1285,39 @@ Function: interpreter void interpreter( const symbol_tablet &symbol_table, - const goto_functionst &goto_functions) + const goto_functionst &goto_functions, + message_handlert &message_handler) { - interpretert interpreter(symbol_table, goto_functions); + interpretert interpreter( + symbol_table, + goto_functions, + message_handler); interpreter(); } + +/*******************************************************************\ + +Function: interpretert::print_memory + + Inputs: + + Outputs: + + Purpose: Prints the current state of the memory map + Since messaget mdofifies class members, print functions are nonconst + +\*******************************************************************/ + +void interpretert::print_memory(bool input_flags) +{ + for(size_t i=0; i(cell.initialized) << ")" + << eom; + debug() << eom; + } +} diff --git a/src/goto-programs/interpreter.h b/src/goto-programs/interpreter.h index bf909502793..1888a009969 100644 --- a/src/goto-programs/interpreter.h +++ b/src/goto-programs/interpreter.h @@ -9,10 +9,13 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_GOTO_PROGRAMS_INTERPRETER_H #define CPROVER_GOTO_PROGRAMS_INTERPRETER_H +#include + #include "goto_functions.h" void interpreter( const symbol_tablet &symbol_table, - const goto_functionst &goto_functions); + const goto_functionst &goto_functions, + message_handlert &message_handler); #endif // CPROVER_GOTO_PROGRAMS_INTERPRETER_H diff --git a/src/goto-programs/interpreter_class.h b/src/goto-programs/interpreter_class.h index 14c429a1a86..83836eea072 100644 --- a/src/goto-programs/interpreter_class.h +++ b/src/goto-programs/interpreter_class.h @@ -14,24 +14,93 @@ Author: Daniel Kroening, kroening@kroening.com #include #include "goto_functions.h" +#include "goto_trace.h" +#include "json_goto_trace.h" +#include "util/message.h" -class interpretert +class interpretert:public messaget { public: interpretert( const symbol_tablet &_symbol_table, - const goto_functionst &_goto_functions): + const goto_functionst &_goto_functions, + message_handlert &_message_handler): + messaget(_message_handler), symbol_table(_symbol_table), ns(_symbol_table), - goto_functions(_goto_functions) + goto_functions(_goto_functions), + stop_on_assertion(false) { + show=true; } void operator()(); + void print_memory(bool input_flags); + + // An assertion that identifier 'id' carries value in some particular context. + // Used to record parameter (id) assignment (value) lists for function calls. + struct function_assignmentt + { + irep_idt id; + exprt value; + }; + + // A list of such assignments. + typedef std::vector function_assignmentst; + + typedef std::vector mp_vectort; + + // Maps an assignment id to the name of the parameter being assigned + typedef std::pair assignment_idt; + + // Identifies an expression before and after some change; + typedef std::pair diff_pairt; + + // Records a diff between an assignment pre and post conditions + typedef std::map side_effects_differencet; + + // A entry in the input_valuest map + typedef std::pair input_entryt; + + // List of the input variables with their corresponding initial values + typedef std::map input_valuest; + + // List of dynamically allocated symbols that are not in the symbol table + typedef std::map dynamic_typest; + + // An assignment list annotated with the calling context. + struct function_assignments_contextt + { + irep_idt calling_function; + function_assignmentst return_assignments; + function_assignmentst param_assignments; + }; + + // list_input_varst maps function identifiers onto a vector of [name = value] + // assignments per call to that function. + typedef std::list + function_assignments_contextst; + typedef std::map > + list_input_varst; + + const dynamic_typest &get_dynamic_types() { return dynamic_types; } protected: + struct trace_stack_entryt + { + irep_idt func_name; + mp_integer this_address; + irep_idt capture_symbol; + bool is_super_call; + std::vector param_values; + }; + typedef std::vector trace_stackt; + const symbol_tablet &symbol_table; + + // This is a cache so that we don't have to create it when a call needs it const namespacet ns; + const goto_functionst &goto_functions; typedef std::unordered_map memory_mapt; @@ -43,16 +112,40 @@ class interpretert irep_idt identifier; unsigned offset; mp_integer value; + // Initialized is annotated even during reads + // Set to 1 when written-before-read, -1 when read-before-written + mutable char initialized; }; typedef std::vector memoryt; - memoryt memory; + typedef std::map parameter_sett; + // mapping -> value + typedef std::pair struct_member_idt; + typedef std::map struct_valuest; + + + // The memory is being annotated/reshaped even during reads + // (ie to find a read-before-write location) thus memory + // properties need to be mutable to avoid making all calls nonconst + mutable memoryt memory; std::size_t stack_pointer; void build_memory_map(); void build_memory_map(const symbolt &symbol); - unsigned get_size(const typet &type) const; + mp_integer build_memory_map(const irep_idt &id, const typet &type); + typet concretize_type(const typet &type); + size_t get_size(const typet &type); + + irep_idt get_component_id(const irep_idt &object, unsigned offset); + typet get_type(const irep_idt &id) const; + exprt get_value( + const typet &type, + std::size_t offset=0, + bool use_non_det=false); + exprt get_value(const typet &type, mp_vectort &rhs, std::size_t offset=0); + exprt get_value(const irep_idt &id); + void step(); void execute_assert(); @@ -62,21 +155,26 @@ class interpretert void execute_function_call(); void execute_other(); void execute_decl(); + void clear_input_flags(); + + void allocate( + mp_integer address, + size_t size); void assign( mp_integer address, - const std::vector &rhs); + const mp_vectort &rhs); void read( mp_integer address, - std::vector &dest) const; + mp_vectort &dest) const; - void command(); + virtual void command(); class stack_framet { public: - goto_programt::const_targett return_PC; + goto_programt::const_targett return_pc; goto_functionst::function_mapt::const_iterator return_function; mp_integer return_value_address; memory_mapt local_map; @@ -84,27 +182,56 @@ class interpretert }; typedef std::stack call_stackt; + call_stackt call_stack; + input_valuest input_vars; + list_input_varst function_input_vars; goto_functionst::function_mapt::const_iterator function; - goto_programt::const_targett PC, next_PC; + goto_programt::const_targett pc, next_pc, target_assert; + goto_tracet steps; bool done; - - bool evaluate_boolean(const exprt &expr) const + bool show; + bool stop_on_assertion; + static const size_t npos; + size_t num_steps; + size_t total_steps; + + dynamic_typest dynamic_types; + int num_dynamic_objects; + size_t stack_depth; + int thread_id; + + bool evaluate_boolean(const exprt &expr) { - std::vector v; + mp_vectort v; evaluate(expr, v); if(v.size()!=1) throw "invalid boolean value"; return v.front()!=0; } + bool count_type_leaves( + const typet &source_type, + mp_integer &result); + + bool byte_offset_to_memory_offset( + const typet &source_type, + mp_integer byte_offset, + mp_integer &result); + + bool memory_offset_to_byte_offset( + const typet &source_type, + mp_integer cell_offset, + mp_integer &result); + void evaluate( const exprt &expr, - std::vector &dest) const; + mp_vectort &dest); - mp_integer evaluate_address(const exprt &expr) const; + mp_integer evaluate_address(const exprt &expr, bool fail_quietly=false); + void initialize(bool init); void show_state(); }; diff --git a/src/goto-programs/interpreter_evaluate.cpp b/src/goto-programs/interpreter_evaluate.cpp index a9d62740cc3..712d4b9d807 100644 --- a/src/goto-programs/interpreter_evaluate.cpp +++ b/src/goto-programs/interpreter_evaluate.cpp @@ -8,42 +8,323 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include #include #include #include +#include +#include #include "interpreter_class.h" /*******************************************************************\ -Function: interpretert::evaluate +Function: interpretert::read Inputs: Outputs: - Purpose: + Purpose: reads a memory address and loads it into the dest variable + marks cell as read before written if cell has never been written \*******************************************************************/ void interpretert::read( mp_integer address, - std::vector &dest) const + mp_vectort &dest) const { // copy memory region - for(auto &d : dest) + for(size_t i=0; i0) + cell.initialized=0; + } +} + +/*******************************************************************\ + +Function: interpretert::count_type_leaves + + Inputs: Type + + Outputs: Number of leaf primitive types; returns true on error + + Purpose: + +\*******************************************************************/ + +bool interpretert::count_type_leaves(const typet &ty, mp_integer &result) +{ + if(ty.id()==ID_struct) + { + result=0; + mp_integer subtype_count; + for(const auto &component : to_struct_type(ty).components()) + { + if(count_type_leaves(component.type(), subtype_count)) + return true; + result+=subtype_count; + } + return false; + } + else if(ty.id()==ID_array) + { + const auto &at=to_array_type(ty); + mp_vectort array_size_vec; + evaluate(at.size(), array_size_vec); + if(array_size_vec.size()!=1) + return true; + mp_integer subtype_count; + if(count_type_leaves(at.subtype(), subtype_count)) + return true; + result=array_size_vec[0]*subtype_count; + return false; + } + else + { + result=1; + return false; + } +} + +/*******************************************************************\ + +Function: interpretert::byte_offset_to_memory_offset + + Inputs: 'source_type', 'offset' (unit: bytes), + + Outputs: Offset into a vector of interpreter values; returns true on error + + Purpose: Supposing the caller has an mp_vector representing + a value with type 'source_type', this yields the offset into that + vector at which to find a value at *byte* address 'offset'. + We need this because the interpreter's memory map uses unlabelled + variable-width values -- for example, a C value { { 1, 2 }, 3, 4 } + of type struct { int x[2]; char y; unsigned long z; } + would be represented [1,2,3,4], with the source type needed alongside + to figure out which member is targeted by a byte-extract operation. + +\*******************************************************************/ + +bool interpretert::byte_offset_to_memory_offset( + const typet &source_type, + mp_integer offset, + mp_integer &result) +{ + if(source_type.id()==ID_struct) + { + const auto &st=to_struct_type(source_type); + const struct_typet::componentst &components=st.components(); + member_offset_iterator component_offsets(st, ns); + mp_integer previous_member_offsets=0; + for(; component_offsets->firstsecond!=-1 && + component_offsets->second<=offset; + ++component_offsets) + { + const auto &component_type=components[component_offsets->first].type(); + mp_integer component_byte_size=pointer_offset_size(component_type, ns); + if(component_byte_size<0) + return true; + if((component_offsets->second+component_byte_size)>offset) + { + mp_integer subtype_result; + bool ret=byte_offset_to_memory_offset( + component_type, + offset-(component_offsets->second), + subtype_result); + result=previous_member_offsets+subtype_result; + return ret; + } + else + { + mp_integer component_count; + if(count_type_leaves(component_type, component_count)) + return true; + previous_member_offsets+=component_count; + } + } + // Ran out of struct members, or struct contained a variable-length field. + return true; + } + else if(source_type.id()==ID_array) + { + const auto &at=to_array_type(source_type); + mp_vectort array_size_vec; + evaluate(at.size(), array_size_vec); + if(array_size_vec.size()!=1) + return true; + mp_integer array_size=array_size_vec[0]; + mp_integer elem_size_bytes=pointer_offset_size(at.subtype(), ns); + if(elem_size_bytes<=0) + return true; + mp_integer elem_size_leaves; + if(count_type_leaves(at.subtype(), elem_size_leaves)) + return true; + mp_integer this_idx=offset/elem_size_bytes; + if(this_idx>=array_size_vec[0]) + return true; + mp_integer subtype_result; + bool ret=byte_offset_to_memory_offset( + at.subtype(), + offset%elem_size_bytes, + subtype_result); + result=subtype_result+(elem_size_leaves*this_idx); + return ret; + } + else + { + result=0; + // Can't currently subdivide a primitive. + return offset!=0; + } +} + +/*******************************************************************\ + +Function: interpretert::memory_offset_to_byte_offset - ++address; + Inputs: An interpreter memory offset and the type to interpret that memory + + Outputs: The corresponding byte offset. Returns true on error + + Purpose: Similarly to the above, the interpreter's memory objects contain + mp_integers that represent variable-sized struct members. This + counts the size of type leaves to determine the byte offset + corresponding to a memory offset. + +\*******************************************************************/ + +bool interpretert::memory_offset_to_byte_offset( + const typet &source_type, + mp_integer cell_offset, + mp_integer &result) +{ + if(source_type.id()==ID_struct) + { + const auto &st=to_struct_type(source_type); + const struct_typet::componentst &components=st.components(); + member_offset_iterator offsets(st, ns); + mp_integer previous_member_sizes; + for(; offsets->firstsecond!=-1; ++offsets) + { + const auto &component_type=components[offsets->first].type(); + mp_integer component_count; + if(count_type_leaves(component_type, component_count)) + return true; + if(component_count>cell_offset) + { + mp_integer subtype_result; + bool ret=memory_offset_to_byte_offset( + component_type, + cell_offset, + subtype_result); + result=previous_member_sizes+subtype_result; + return ret; + } + else + { + cell_offset-=component_count; + mp_integer component_size=pointer_offset_size(component_type, ns); + if(component_size<0) + return true; + previous_member_sizes+=component_size; + } + } + // Ran out of members, or member of indefinite size + return true; + } + else if(source_type.id()==ID_array) + { + const auto &at=to_array_type(source_type); + mp_vectort array_size_vec; + evaluate(at.size(), array_size_vec); + if(array_size_vec.size()!=1) + return true; + mp_integer elem_size=pointer_offset_size(at.subtype(), ns); + if(elem_size==-1) + return true; + mp_integer elem_count; + if(count_type_leaves(at.subtype(), elem_count)) + return true; + mp_integer this_idx=cell_offset/elem_count; + if(this_idx>=array_size_vec[0]) + return true; + mp_integer subtype_result; + bool ret= + memory_offset_to_byte_offset(at.subtype(), + cell_offset%elem_count, + subtype_result); + result=subtype_result+(elem_size*this_idx); + return ret; + } + else + { + // Primitive type. + result=0; + return cell_offset!=0; } } @@ -61,12 +342,55 @@ Function: interpretert::evaluate void interpretert::evaluate( const exprt &expr, - std::vector &dest) const + mp_vectort &dest) { if(expr.id()==ID_constant) { if(expr.type().id()==ID_struct) { + dest.reserve(get_size(expr.type())); + bool error=false; + + forall_operands(it, expr) + { + if(it->type().id()==ID_code) + continue; + + size_t sub_size=get_size(it->type()); + if(sub_size==0) + continue; + + mp_vectort tmp; + evaluate(*it, tmp); + + if(tmp.size()==sub_size) + { + for(size_t i=0; itype().id()==ID_code) continue; - unsigned sub_size=get_size(it->type()); + size_t sub_size=get_size(it->type()); if(sub_size==0) continue; - std::vector tmp; + mp_vectort tmp; evaluate(*it, tmp); if(tmp.size()==sub_size) { - for(unsigned i=0; i tmp0, tmp1; + mp_vectort tmp0, tmp1; evaluate(expr.op0(), tmp0); evaluate(expr.op1(), tmp1); @@ -172,7 +691,7 @@ void interpretert::evaluate( forall_operands(it, expr) { - std::vector tmp; + mp_vectort tmp; evaluate(*it, tmp); if(tmp.size()==1 && tmp.front()!=0) @@ -191,20 +710,20 @@ void interpretert::evaluate( if(expr.operands().size()!=3) throw "if expects three operands"; - std::vector tmp0, tmp1, tmp2; + mp_vectort tmp0, tmp1; evaluate(expr.op0(), tmp0); - evaluate(expr.op1(), tmp1); - evaluate(expr.op2(), tmp2); - if(tmp0.size()==1 && tmp1.size()==1 && tmp2.size()==1) + if(tmp0.size()==1) { - const mp_integer &op0=tmp0.front(); - const mp_integer &op1=tmp1.front(); - const mp_integer &op2=tmp2.front(); - - dest.push_back(op0!=0?op1:op2); + if(tmp0.front()!=0) + evaluate(expr.op1(), tmp1); + else + evaluate(expr.op2(), tmp1); } + if(tmp1.size()==1) + dest.push_back(tmp1.front()); + return; } else if(expr.id()==ID_and) @@ -216,7 +735,7 @@ void interpretert::evaluate( forall_operands(it, expr) { - std::vector tmp; + mp_vectort tmp; evaluate(*it, tmp); if(tmp.size()==1 && tmp.front()==0) @@ -235,7 +754,7 @@ void interpretert::evaluate( if(expr.operands().size()!=1) throw id2string(expr.id())+" expects one operand"; - std::vector tmp; + mp_vectort tmp; evaluate(expr.op0(), tmp); if(tmp.size()==1) @@ -249,7 +768,7 @@ void interpretert::evaluate( forall_operands(it, expr) { - std::vector tmp; + mp_vectort tmp; evaluate(*it, tmp); if(tmp.size()==1) result+=tmp.front(); @@ -281,7 +800,7 @@ void interpretert::evaluate( forall_operands(it, expr) { - std::vector tmp; + mp_vectort tmp; evaluate(*it, tmp); if(tmp.size()==1) { @@ -317,7 +836,7 @@ void interpretert::evaluate( if(expr.operands().size()!=2) throw "- expects two operands"; - std::vector tmp0, tmp1; + mp_vectort tmp0, tmp1; evaluate(expr.op0(), tmp0); evaluate(expr.op1(), tmp1); @@ -330,7 +849,7 @@ void interpretert::evaluate( if(expr.operands().size()!=2) throw "/ expects two operands"; - std::vector tmp0, tmp1; + mp_vectort tmp0, tmp1; evaluate(expr.op0(), tmp0); evaluate(expr.op1(), tmp1); @@ -343,7 +862,7 @@ void interpretert::evaluate( if(expr.operands().size()!=1) throw "unary- expects one operand"; - std::vector tmp0; + mp_vectort tmp0; evaluate(expr.op0(), tmp0); if(tmp0.size()==1) @@ -358,22 +877,130 @@ void interpretert::evaluate( dest.push_back(evaluate_address(expr.op0())); return; } + else if(expr.id()==ID_pointer_offset) + { + if(expr.operands().size()!=1) + throw "pointer_offset expects one operand"; + if(expr.op0().type().id()!=ID_pointer) + throw "pointer_offset expects a pointer operand"; + mp_vectort result; + evaluate(expr.op0(), result); + if(result.size()==1) + { + // Return the distance, in bytes, between the address returned + // and the beginning of the underlying object. + mp_integer address=result[0]; + if(address>0 && address0) + { + dest.insert(dest.end(), + extract_from.begin()+memory_offset.to_long(), + extract_from.begin()+(memory_offset+target_type_leaves).to_long()); + return; + } + } + } + } else if(expr.id()==ID_dereference || expr.id()==ID_index || expr.id()==ID_symbol || expr.id()==ID_member) { - mp_integer a=evaluate_address(expr); - dest.resize(get_size(expr.type())); - read(a, dest); - return; + mp_integer address=evaluate_address( + expr, + true); // fail quietly + if(address.is_zero() && expr.id()==ID_index) + { + // Try reading from a constant array: + mp_vectort idx; + evaluate(expr.op1(), idx); + if(idx.size()==1) + { + mp_integer read_from_index=idx[0]; + if(expr.op0().id()==ID_array) + { + const auto &ops=expr.op0().operands(); + assert(read_from_index.is_long()); + if(read_from_index>=0 && read_from_index tmp; + mp_vectort tmp; evaluate(expr.op0(), tmp); if(tmp.size()==1) @@ -399,31 +1026,38 @@ void interpretert::evaluate( dest.push_back(binary2integer(s, false)); return; } - else if(expr.type().id()==ID_bool) + else if((expr.type().id()==ID_bool) || (expr.type().id()==ID_c_bool)) { dest.push_back(value!=0); return; } } } - else if(expr.id()==ID_ashr) + else if((expr.id()==ID_array) || (expr.id()==ID_array_of)) { - if(expr.operands().size()!=2) - throw "ashr expects two operands"; - - std::vector tmp0, tmp1; - evaluate(expr.op0(), tmp0); - evaluate(expr.op1(), tmp1); - - if(tmp0.size()==1 && tmp1.size()==1) - dest.push_back(tmp0.front()/power(2, tmp1.front())); - + forall_operands(it, expr) + { + evaluate(*it, dest); + } return; } - - std::cout << "!! failed to evaluate expression: " - << from_expr(ns, function->first, expr) - << std::endl; + else if(expr.id()==ID_nil) + { + dest.push_back(0); + return; + } + else if(expr.id()==ID_infinity) + { + if(expr.type().id()==ID_signedbv) + { + error() << "Infinite size arrays not supported" << eom; + return; + } + } + error() << "!! failed to evaluate expression: " + << from_expr(ns, function->first, expr) << "\n" + << expr.id() << "[" << expr.type().id() << "]" + << eom; } /*******************************************************************\ @@ -438,11 +1072,16 @@ Function: interpretert::evaluate_address \*******************************************************************/ -mp_integer interpretert::evaluate_address(const exprt &expr) const +mp_integer interpretert::evaluate_address( + const exprt &expr, + bool fail_quietly) { if(expr.id()==ID_symbol) { - const irep_idt &identifier=expr.get(ID_identifier); + const irep_idt &identifier= + is_ssa_expr(expr) ? + to_ssa_expr(expr).get_original_name() : + expr.get(ID_identifier); interpretert::memory_mapt::const_iterator m_it1= memory_map.find(identifier); @@ -458,13 +1097,16 @@ mp_integer interpretert::evaluate_address(const exprt &expr) const if(m_it2!=call_stack.top().local_map.end()) return m_it2->second; } + mp_integer address=memory.size(); + build_memory_map(to_symbol_expr(expr).get_identifier(), expr.type()); + return address; } else if(expr.id()==ID_dereference) { if(expr.operands().size()!=1) throw "dereference expects one operand"; - std::vector tmp0; + mp_vectort tmp0; evaluate(expr.op0(), tmp0); if(tmp0.size()==1) @@ -475,11 +1117,15 @@ mp_integer interpretert::evaluate_address(const exprt &expr) const if(expr.operands().size()!=2) throw "index expects two operands"; - std::vector tmp1; + mp_vectort tmp1; evaluate(expr.op1(), tmp1); if(tmp1.size()==1) - return evaluate_address(expr.op0())+tmp1.front(); + { + auto base=evaluate_address(expr.op0(), fail_quietly); + if(!base.is_zero()) + return base+tmp1.front(); + } } else if(expr.id()==ID_member) { @@ -502,12 +1148,44 @@ mp_integer interpretert::evaluate_address(const exprt &expr) const offset+=get_size(comp.type()); } - return evaluate_address(expr.op0())+offset; + auto base=evaluate_address(expr.op0(), fail_quietly); + if(!base.is_zero()) + return base+offset; } - - std::cout << "!! failed to evaluate address: " + else if(expr.id()==ID_byte_extract_little_endian || + expr.id()==ID_byte_extract_big_endian) + { + if(expr.operands().size()!=2) + throw "byte_extract should have two operands"; + mp_vectort extract_offset; + evaluate(expr.op1(), extract_offset); + mp_vectort extract_from; + evaluate(expr.op0(), extract_from); + if(extract_offset.size()==1 && !extract_from.empty()) + { + mp_integer memory_offset; + if(!byte_offset_to_memory_offset(expr.op0().type(), + extract_offset[0], memory_offset)) + return evaluate_address(expr.op0(), fail_quietly)+memory_offset; + } + } + else if(expr.id()==ID_if) + { + mp_vectort result; + if_exprt address_cond( + expr.op0(), + address_of_exprt(expr.op1()), + address_of_exprt(expr.op2())); + evaluate(address_cond, result); + if(result.size()==1) + return result[0]; + } + if(!fail_quietly) + { + error() << "!! failed to evaluate address: " << from_expr(ns, function->first, expr) - << std::endl; + << eom; + } return 0; } From c09db527d36955acb071bfa7d9ebfe63942752d7 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 1 Dec 2016 16:06:24 +0000 Subject: [PATCH 061/699] Generate stub method for opaque functions Initial commit making a stub function in the GOTO program for any opaque functions (i.e. functions for which we don't have a body). This is done to ensure we can match up the assignments after the opaque function to the return from the opaque function. --- src/util/language.cpp | 85 +++++++++++++++++++++++++++++++++++++++++++ src/util/language.h | 10 +++++ 2 files changed, 95 insertions(+) diff --git a/src/util/language.cpp b/src/util/language.cpp index 4b4a1ba4ae4..ff2eb4858b4 100644 --- a/src/util/language.cpp +++ b/src/util/language.cpp @@ -8,6 +8,8 @@ Author: Daniel Kroening, kroening@kroening.com #include "language.h" #include "expr.h" +#include +#include /*******************************************************************\ @@ -125,3 +127,86 @@ bool languaget::type_to_name( name=type.pretty(); return false; } + +/*******************************************************************\ + +Function: languaget::generate_opaque_method_stubs + + Inputs: + symbol_table - the symbol table for the program + + Outputs: + + Purpose: When there are opaque methods (e.g. ones where we don't + have a body), we create a stub function in the goto + program and mark it as opaque so the interpreter fills in + appropriate values for it. + +\*******************************************************************/ + +void languaget::generate_opaque_method_stubs(symbol_tablet &symbol_table) +{ + for(auto &symbol_entry : symbol_table.symbols) + { + if(is_symbol_opaque_function(symbol_entry.second)) + { + symbolt &symbol=symbol_entry.second; + + irep_idt return_symbol_id = generate_opaque_stub_body( + symbol, + symbol_table); + + if(return_symbol_id!=ID_nil) + { + symbol.type.set("opaque_method_capture_symbol", return_symbol_id); + } + } + } +} + +/*******************************************************************\ + +Function: languaget::generate_opaque_stub_body + + Inputs: + symbol - the function symbol which is opaque + symbol_table - the symbol table + + Outputs: The identifier of the return variable. ID_nil if the function + doesn't return anything. + + Purpose: To generate the stub function for the opaque function in + question. The identifier is used in the flag to the interpreter + that the function is opaque. This function should be implemented + in the languages. + +\*******************************************************************/ + +irep_idt languaget::generate_opaque_stub_body( + symbolt &symbol, + symbol_tablet &symbol_table) +{ + return ID_nil; +} + + +/*******************************************************************\ + +Function: languaget::is_symbol_opaque_function + + Inputs: + symbol - the symbol to be checked + + Outputs: True if the symbol is an opaque (e.g. non-bodied) function + + Purpose: To identify if a given symbol is an opaque function and + hence needs to be stubbed + +\*******************************************************************/ + +bool languaget::is_symbol_opaque_function(const symbolt &symbol) +{ + return !symbol.is_type && + symbol.value.id()==ID_nil && + symbol.type.id()==ID_code; +} diff --git a/src/util/language.h b/src/util/language.h index b19615496ec..5f284131a0e 100644 --- a/src/util/language.h +++ b/src/util/language.h @@ -16,6 +16,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "message.h" class symbol_tablet; +class symbolt; class exprt; class namespacet; class typet; @@ -114,5 +115,14 @@ class languaget:public messaget languaget() { } virtual ~languaget() { } + +protected: + void generate_opaque_method_stubs(symbol_tablet &symbol_table); + virtual irep_idt generate_opaque_stub_body( + symbolt &symbol, + symbol_tablet &symbol_table); + +private: + bool is_symbol_opaque_function(const symbolt &symbol); }; #endif // CPROVER_UTIL_LANGUAGE_H From 35d847be9c8248a5f3731220d69daa2051926b8a Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 2 Dec 2016 11:01:14 +0000 Subject: [PATCH 062/699] Don't create stub for CPROVER_ functions These were having stubs created but they are not opaque functions. This was because their body gets created after this step. --- src/util/language.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/util/language.cpp b/src/util/language.cpp index ff2eb4858b4..cecc7944f88 100644 --- a/src/util/language.cpp +++ b/src/util/language.cpp @@ -10,6 +10,8 @@ Author: Daniel Kroening, kroening@kroening.com #include "expr.h" #include #include +#include +#include /*******************************************************************\ @@ -200,13 +202,20 @@ Function: languaget::is_symbol_opaque_function Outputs: True if the symbol is an opaque (e.g. non-bodied) function Purpose: To identify if a given symbol is an opaque function and - hence needs to be stubbed + hence needs to be stubbed. We explicitly exclude CPROVER + functions, if they have no body it is because we haven't + generated it yet. \*******************************************************************/ bool languaget::is_symbol_opaque_function(const symbolt &symbol) { + // Explictly exclude CPROVER functions since these aren't opaque + std::string variable_id_str(symbol.name.c_str()); + bool is_cprover_function = has_prefix(variable_id_str, CPROVER_PREFIX); + return !symbol.is_type && symbol.value.id()==ID_nil && - symbol.type.id()==ID_code; + symbol.type.id()==ID_code && + !is_cprover_function; } From 53f4a9905b82aa8b5abbc0775b4117f4bbd1fe8c Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 2 Dec 2016 12:11:25 +0000 Subject: [PATCH 063/699] Create stub argument identifiers for functions with parameters If opaque functions do not name there parameters, it causes issues later when we try to call the stub functions. This creates dummy symbols and names the parameters in the function type. --- src/util/language.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++ src/util/language.h | 9 +++++- 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/util/language.cpp b/src/util/language.cpp index cecc7944f88..7349b09ed1f 100644 --- a/src/util/language.cpp +++ b/src/util/language.cpp @@ -12,6 +12,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include /*******************************************************************\ @@ -154,6 +155,8 @@ void languaget::generate_opaque_method_stubs(symbol_tablet &symbol_table) { symbolt &symbol=symbol_entry.second; + generate_opaque_parameter_symbols(symbol, symbol_table); + irep_idt return_symbol_id = generate_opaque_stub_body( symbol, symbol_table); @@ -191,6 +194,36 @@ irep_idt languaget::generate_opaque_stub_body( return ID_nil; } +/*******************************************************************\ + +Function: languaget::build_stub_parameter_symbol + + Inputs: + function_symbol - the symbol of an opaque function + parameter_index - the index of the parameter within the + the parameter list + parameter_type - the type of the parameter + + Outputs: A named symbol to be added to the symbol table representing + one of the parameters in this opaque function. + + Purpose: To build the parameter symbol and choose its name. This should + be implemented in each language. + +\*******************************************************************/ + +parameter_symbolt languaget::build_stub_parameter_symbol( + const symbolt &function_symbol, + size_t parameter_index, + const typet ¶meter_type) +{ + error() << "language " << id() + << " doesn't implement build_stub_parameter_symbol. " + << "This means cannot use opaque functions." << eom; + + return parameter_symbolt(); +} + /*******************************************************************\ @@ -219,3 +252,39 @@ bool languaget::is_symbol_opaque_function(const symbolt &symbol) symbol.type.id()==ID_code && !is_cprover_function; } + +/*******************************************************************\ + +Function: languaget::generate_opaque_parameter_symbols + + Inputs: + function_symbol - the symbol of an opaque function + symbol_table - the symbol table to add the new parameter + symbols into + + Outputs: + + Purpose: To create stub parameter symbols for each parameter the + function has and assign their IDs into the parameters + identifier. + +\*******************************************************************/ + +void languaget::generate_opaque_parameter_symbols( + symbolt &function_symbol, + symbol_tablet &symbol_table) +{ + code_typet &function_type = to_code_type(function_symbol.type); + code_typet::parameterst ¶meters=function_type.parameters(); + for(std::size_t i=0; i #include #include +#include #include "message.h" class symbol_tablet; -class symbolt; class exprt; class namespacet; class typet; @@ -122,7 +122,14 @@ class languaget:public messaget symbolt &symbol, symbol_tablet &symbol_table); + virtual parameter_symbolt build_stub_parameter_symbol( + const symbolt &function_symbol, + size_t parameter_index, + const typet ¶meter_type); private: bool is_symbol_opaque_function(const symbolt &symbol); + void generate_opaque_parameter_symbols( + symbolt &function_symbol, + symbol_tablet &symbol_table); }; #endif // CPROVER_UTIL_LANGUAGE_H From 18b1445a911531202d32e39e80994a88daecdef8 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 2 Dec 2016 12:52:04 +0000 Subject: [PATCH 064/699] Pass the whole parameter in when generating the symbol This allows for the symbol builder to inspect other properties of the type (e.g. is is a this parameter). --- src/util/language.cpp | 4 ++-- src/util/language.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/util/language.cpp b/src/util/language.cpp index 7349b09ed1f..b88a7c2f3c7 100644 --- a/src/util/language.cpp +++ b/src/util/language.cpp @@ -215,7 +215,7 @@ Function: languaget::build_stub_parameter_symbol parameter_symbolt languaget::build_stub_parameter_symbol( const symbolt &function_symbol, size_t parameter_index, - const typet ¶meter_type) + const code_typet::parametert ¶meter) { error() << "language " << id() << " doesn't implement build_stub_parameter_symbol. " @@ -280,7 +280,7 @@ void languaget::generate_opaque_parameter_symbols( { code_typet::parametert ¶m=parameters[i]; const parameter_symbolt ¶m_symbol= - build_stub_parameter_symbol(function_symbol, i, param.type()); + build_stub_parameter_symbol(function_symbol, i, param); param.set_base_name(param_symbol.base_name); param.set_identifier(param_symbol.name); diff --git a/src/util/language.h b/src/util/language.h index 9ec92ebc406..214b9ed2813 100644 --- a/src/util/language.h +++ b/src/util/language.h @@ -13,6 +13,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include #include "message.h" @@ -125,7 +126,7 @@ class languaget:public messaget virtual parameter_symbolt build_stub_parameter_symbol( const symbolt &function_symbol, size_t parameter_index, - const typet ¶meter_type); + const code_typet::parametert ¶meter); private: bool is_symbol_opaque_function(const symbolt &symbol); void generate_opaque_parameter_symbols( From dddb5522f22955c49fb0ac2488cd74fc1e023bdb Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 5 Dec 2016 14:30:57 +0000 Subject: [PATCH 065/699] Refactored method for generating return symbol name to languaget The name for the return symbol is now generated by languaget. This is so the name is consistent across different language implementations. --- src/util/language.cpp | 22 ++++++++++++++++++++++ src/util/language.h | 3 +++ 2 files changed, 25 insertions(+) diff --git a/src/util/language.cpp b/src/util/language.cpp index b88a7c2f3c7..d395d063903 100644 --- a/src/util/language.cpp +++ b/src/util/language.cpp @@ -224,6 +224,28 @@ parameter_symbolt languaget::build_stub_parameter_symbol( return parameter_symbolt(); } +/*******************************************************************\ + +Function: languaget::get_stub_return_symbol_name + + Inputs: + function_id - the function that has a return value + + Outputs: the identifier to use for the symbol that will store the + return value of this function. + + Purpose: To get the name of the symbol to be used for the return value + of the function. Generates a name like to_return_function_name + +\*******************************************************************/ + +irep_idt languaget::get_stub_return_symbol_name(const irep_idt &function_id) +{ + std::ostringstream return_symbol_name_builder; + return_symbol_name_builder << "to_return_" << function_id; + return return_symbol_name_builder.str(); +} + /*******************************************************************\ diff --git a/src/util/language.h b/src/util/language.h index 214b9ed2813..d78477e8ab4 100644 --- a/src/util/language.h +++ b/src/util/language.h @@ -127,6 +127,9 @@ class languaget:public messaget const symbolt &function_symbol, size_t parameter_index, const code_typet::parametert ¶meter); + + static irep_idt get_stub_return_symbol_name(const irep_idt &function_id); + private: bool is_symbol_opaque_function(const symbolt &symbol); void generate_opaque_parameter_symbols( From e11fd638454fddeefe3ee0cabdef3dcfc1050551 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 17 Jan 2017 12:43:22 +0000 Subject: [PATCH 066/699] Added a flag for enabling opaque method stubs As some tests were verifying the functions didn't exist, we need a flag to turn it on or off. Stubs default to off and are turned on by the flag --generate-opaque-stubs. This is an option in CBMC but perhaps it could be applied to other programs (e.g. applied when compiling C to GOTO). --- src/langapi/language_ui.cpp | 4 ++++ src/util/language.cpp | 44 +++++++++++++++++++++++++++---------- src/util/language.h | 4 ++++ src/util/language_file.cpp | 22 +++++++++++++++++++ src/util/language_file.h | 2 ++ 5 files changed, 65 insertions(+), 11 deletions(-) diff --git a/src/langapi/language_ui.cpp b/src/langapi/language_ui.cpp index 95b5d104a4f..4b0f3fa0d75 100644 --- a/src/langapi/language_ui.cpp +++ b/src/langapi/language_ui.cpp @@ -183,6 +183,10 @@ bool language_uit::final() { language_files.set_message_handler(*message_handler); + // Enable/disable stub generation for opaque methods + bool stubs_enabled=_cmdline.isset("generate-opaque-stubs"); + language_files.set_should_generate_opaque_method_stubs(stubs_enabled); + if(language_files.final(symbol_table)) { if(get_ui()==ui_message_handlert::PLAIN) diff --git a/src/util/language.cpp b/src/util/language.cpp index d395d063903..2b546f365a5 100644 --- a/src/util/language.cpp +++ b/src/util/language.cpp @@ -133,6 +133,24 @@ bool languaget::type_to_name( /*******************************************************************\ +Function: languaget::set_should_generate_opaque_method_stubs + + Inputs: + should_generate_stubs - Should stub generation be enabled + + Outputs: + + Purpose: Turn on or off stub generation. + +\*******************************************************************/ +void languaget::set_should_generate_opaque_method_stubs( + bool should_generate_stubs) +{ + generate_opaque_stubs=should_generate_stubs; +} + +/*******************************************************************\ + Function: languaget::generate_opaque_method_stubs Inputs: @@ -143,27 +161,31 @@ Function: languaget::generate_opaque_method_stubs Purpose: When there are opaque methods (e.g. ones where we don't have a body), we create a stub function in the goto program and mark it as opaque so the interpreter fills in - appropriate values for it. + appropriate values for it. This will only happen if + generate_opaque_stubs is enabled. \*******************************************************************/ void languaget::generate_opaque_method_stubs(symbol_tablet &symbol_table) { - for(auto &symbol_entry : symbol_table.symbols) + if(generate_opaque_stubs) { - if(is_symbol_opaque_function(symbol_entry.second)) + for(auto &symbol_entry : symbol_table.symbols) { - symbolt &symbol=symbol_entry.second; + if(is_symbol_opaque_function(symbol_entry.second)) + { + symbolt &symbol=symbol_entry.second; - generate_opaque_parameter_symbols(symbol, symbol_table); + generate_opaque_parameter_symbols(symbol, symbol_table); - irep_idt return_symbol_id = generate_opaque_stub_body( - symbol, - symbol_table); + irep_idt return_symbol_id=generate_opaque_stub_body( + symbol, + symbol_table); - if(return_symbol_id!=ID_nil) - { - symbol.type.set("opaque_method_capture_symbol", return_symbol_id); + if(return_symbol_id!=ID_nil) + { + symbol.type.set("opaque_method_capture_symbol", return_symbol_id); + } } } } diff --git a/src/util/language.h b/src/util/language.h index d78477e8ab4..b83bba97c0b 100644 --- a/src/util/language.h +++ b/src/util/language.h @@ -112,6 +112,8 @@ class languaget:public messaget virtual languaget *new_language()=0; + void set_should_generate_opaque_method_stubs(bool should_generate_stubs); + // constructor / destructor languaget() { } @@ -130,6 +132,8 @@ class languaget:public messaget static irep_idt get_stub_return_symbol_name(const irep_idt &function_id); + bool generate_opaque_stubs; + private: bool is_symbol_opaque_function(const symbolt &symbol); void generate_opaque_parameter_symbols( diff --git a/src/util/language_file.cpp b/src/util/language_file.cpp index 46f51564b54..b0fbb47c2f9 100644 --- a/src/util/language_file.cpp +++ b/src/util/language_file.cpp @@ -93,6 +93,28 @@ void language_filest::show_parse(std::ostream &out) /*******************************************************************\ +Function: language_filest::set_should_generate_opqaue_method_stubs + + Inputs: + should_generate_stubs - Should stub generation be enabled + + Outputs: + + Purpose: Turn on or off stub generation for all the languages + +\*******************************************************************/ + +void language_filest::set_should_generate_opaque_method_stubs( + bool stubs_enabled) +{ + for(file_mapt::value_type &language_file_entry : file_map) + { + languaget *language=language_file_entry.second.language; + language->set_should_generate_opaque_method_stubs(stubs_enabled); + } +} + +/*******************************************************************\ Function: language_filest::parse Inputs: diff --git a/src/util/language_file.h b/src/util/language_file.h index d3184d48697..9fffc7f14f1 100644 --- a/src/util/language_file.h +++ b/src/util/language_file.h @@ -75,6 +75,8 @@ class language_filest:public messaget file_map.clear(); } + void set_should_generate_opaque_method_stubs(bool stubs_enabled); + bool parse(); void show_parse(std::ostream &out); From a1014a13f642dbbd4d25338af5cd044810eb2e9e Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 16 Jan 2017 17:03:48 +0000 Subject: [PATCH 067/699] Use the system_library_symbols when generating stubs We don't want to generate stubs for any of these symbols as they have proper internal implementaions that CBMC knows about. --- src/util/language.cpp | 9 +++++---- src/util/language.h | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/util/language.cpp b/src/util/language.cpp index 2b546f365a5..5a5eb2417ea 100644 --- a/src/util/language.cpp +++ b/src/util/language.cpp @@ -170,6 +170,8 @@ void languaget::generate_opaque_method_stubs(symbol_tablet &symbol_table) { if(generate_opaque_stubs) { + system_symbols=system_library_symbolst(); + for(auto &symbol_entry : symbol_table.symbols) { if(is_symbol_opaque_function(symbol_entry.second)) @@ -287,14 +289,13 @@ Function: languaget::is_symbol_opaque_function bool languaget::is_symbol_opaque_function(const symbolt &symbol) { - // Explictly exclude CPROVER functions since these aren't opaque - std::string variable_id_str(symbol.name.c_str()); - bool is_cprover_function = has_prefix(variable_id_str, CPROVER_PREFIX); + std::set headers; + bool is_internal=system_symbols.is_symbol_internal_symbol(symbol, headers); return !symbol.is_type && symbol.value.id()==ID_nil && symbol.type.id()==ID_code && - !is_cprover_function; + !is_internal; } /*******************************************************************\ diff --git a/src/util/language.h b/src/util/language.h index b83bba97c0b..73ead1cd8e4 100644 --- a/src/util/language.h +++ b/src/util/language.h @@ -14,6 +14,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include #include "message.h" @@ -139,5 +140,7 @@ class languaget:public messaget void generate_opaque_parameter_symbols( symbolt &function_symbol, symbol_tablet &symbol_table); + + system_library_symbolst system_symbols; }; #endif // CPROVER_UTIL_LANGUAGE_H From 4e6b2a290593f74beb146885143a6907b097705e Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 19 Jan 2017 10:54:04 +0000 Subject: [PATCH 068/699] Added comment explaining the type of symbols we aren't stubbing --- src/util/language.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/util/language.cpp b/src/util/language.cpp index 5a5eb2417ea..ddb41979040 100644 --- a/src/util/language.cpp +++ b/src/util/language.cpp @@ -290,6 +290,9 @@ Function: languaget::is_symbol_opaque_function bool languaget::is_symbol_opaque_function(const symbolt &symbol) { std::set headers; + // Don't create stubs for symbols like: + // __CPROVER_blah (which aren't real external functions) + // and strstr (which we will model for ourselves later) bool is_internal=system_symbols.is_symbol_internal_symbol(symbol, headers); return !symbol.is_type && From e2614efa439d3a9084083681440968a351c79ca9 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 8 Nov 2016 17:03:58 +0000 Subject: [PATCH 069/699] Adding simple regression for struct function Also made test logs be ignored but git. This test currently fails (correctly) as the integer member of the struct is not being set to the correct value --- regression/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 regression/.gitignore diff --git a/regression/.gitignore b/regression/.gitignore new file mode 100644 index 00000000000..750ecf9f446 --- /dev/null +++ b/regression/.gitignore @@ -0,0 +1 @@ +tests.log From fa73b8bcb56dfadc496f2ec3d1f1bd4c8429736c Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 9 Dec 2016 16:42:13 +0000 Subject: [PATCH 070/699] Use the symbol in expr2c --- src/ansi-c/expr2c.cpp | 46 +++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/ansi-c/expr2c.cpp b/src/ansi-c/expr2c.cpp index a6975bdab19..5de8c7688b0 100644 --- a/src/ansi-c/expr2c.cpp +++ b/src/ansi-c/expr2c.cpp @@ -518,28 +518,40 @@ std::string expr2ct::convert_rec( } else if(src.id()==ID_symbol) { - const typet &followed=ns.follow(src); + symbol_typet symbolic_type=to_symbol_type(src); + const irep_idt &typedef_identifer=symbolic_type.get(ID_typedef); - if(followed.id()==ID_struct) + // Providing we have a valid identifer, we can just use that rather than + // trying to find the concrete type + if(typedef_identifer!="") { - std::string dest=q+"struct"; - const irep_idt &tag=to_struct_type(followed).get_tag(); - if(tag!="") - dest+=" "+id2string(tag); - dest+=d; - return dest; + return q+id2string(typedef_identifer)+d; } - else if(followed.id()==ID_union) + else { - std::string dest=q+"union"; - const irep_idt &tag=to_union_type(followed).get_tag(); - if(tag!="") - dest+=" "+id2string(tag); - dest+=d; - return dest; + const typet &followed=ns.follow(src); + + if(followed.id()==ID_struct) + { + std::string dest=q+"struct"; + const irep_idt &tag=to_struct_type(followed).get_tag(); + if(tag!="") + dest+=" "+id2string(tag); + dest+=d; + return dest; + } + else if(followed.id()==ID_union) + { + std::string dest=q+"union"; + const irep_idt &tag=to_union_type(followed).get_tag(); + if(tag!="") + dest+=" "+id2string(tag); + dest+=d; + return dest; + } + else + return convert_rec(followed, new_qualifiers, declarator); } - else - return convert_rec(followed, new_qualifiers, declarator); } else if(src.id()==ID_struct_tag) { From 8dd297e5a715697abc8ea9014675507b63201a35 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 10 Mar 2017 11:28:43 +0000 Subject: [PATCH 071/699] Call the generate_opqaue_stubs from final This doesn't do anything if it is not enabled --- src/ansi-c/ansi_c_language.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ansi-c/ansi_c_language.cpp b/src/ansi-c/ansi_c_language.cpp index dc69515ede2..159b0d6df40 100644 --- a/src/ansi-c/ansi_c_language.cpp +++ b/src/ansi-c/ansi_c_language.cpp @@ -196,6 +196,8 @@ Function: ansi_c_languaget::final bool ansi_c_languaget::final(symbol_tablet &symbol_table) { + generate_opaque_method_stubs(symbol_table); + if(ansi_c_entry_point(symbol_table, "main", get_message_handler())) return true; From 8236166af0d60f4cb74e7be93d567f4d3e4552df Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 7 Mar 2017 18:01:34 +0000 Subject: [PATCH 072/699] Changes to get java compiling --- src/java_bytecode/java_entry_point.h | 2 ++ src/java_bytecode/java_object_factory.cpp | 3 ++- src/java_bytecode/java_object_factory.h | 10 +++++++++- src/java_bytecode/java_types.cpp | 18 ++++++++++++++++++ src/java_bytecode/java_types.h | 2 ++ 5 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/java_bytecode/java_entry_point.h b/src/java_bytecode/java_entry_point.h index e6575734d80..6a1576c6a4c 100644 --- a/src/java_bytecode/java_entry_point.h +++ b/src/java_bytecode/java_entry_point.h @@ -11,6 +11,8 @@ Author: Daniel Kroening, kroening@kroening.com #include +#define JAVA_ENTRY_POINT_RETURN_SYMBOL "return'" + bool java_entry_point( class symbol_tablet &symbol_table, const irep_idt &main_class, diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index b23e419d216..4cb8b19a496 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -483,7 +483,8 @@ void gen_nondet_init( bool create_dyn_objs, bool assume_non_null, message_handlert &message_handler, - size_t max_nondet_array_length) + size_t max_nondet_array_length, + update_in_placet update_in_place) { java_object_factoryt state( init_code, diff --git a/src/java_bytecode/java_object_factory.h b/src/java_bytecode/java_object_factory.h index d111948e365..f0b77b343fb 100644 --- a/src/java_bytecode/java_object_factory.h +++ b/src/java_bytecode/java_object_factory.h @@ -22,6 +22,13 @@ exprt object_factory( const source_locationt &, message_handlert &message_handler); +enum update_in_placet +{ + NO_UPDATE_IN_PLACE, + MAY_UPDATE_IN_PLACE, + MUST_UPDATE_IN_PLACE +}; + void gen_nondet_init( const exprt &expr, code_blockt &init_code, @@ -31,7 +38,8 @@ void gen_nondet_init( bool create_dynamic_objects, bool assume_non_null, message_handlert &message_handler, - size_t max_nondet_array_length=5); + size_t max_nondet_array_length, + update_in_placet update_in_place=NO_UPDATE_IN_PLACE); exprt get_nondet_bool(const typet &); diff --git a/src/java_bytecode/java_types.cpp b/src/java_bytecode/java_types.cpp index 735a2a0dbfb..9d78c7a36a7 100644 --- a/src/java_bytecode/java_types.cpp +++ b/src/java_bytecode/java_types.cpp @@ -9,6 +9,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include #include #include #include @@ -231,6 +232,23 @@ pointer_typet java_array_type(const char subtype) /*******************************************************************\ +Function: is_java_array_tag + + Inputs: Struct tag 'tag' + + Outputs: True if the given struct is a Java array + + Purpose: See above + +\*******************************************************************/ + +bool is_java_array_tag(const irep_idt& tag) +{ + return has_prefix(id2string(tag), "java::array["); +} + +/*******************************************************************\ + Function: is_reference_type Inputs: diff --git a/src/java_bytecode/java_types.h b/src/java_bytecode/java_types.h index e283a5acf23..2b32d5fec43 100644 --- a/src/java_bytecode/java_types.h +++ b/src/java_bytecode/java_types.h @@ -44,4 +44,6 @@ char java_char_from_type(const typet &type); typet java_bytecode_promotion(const typet &); exprt java_bytecode_promotion(const exprt &); +bool is_java_array_tag(const irep_idt& tag); + #endif // CPROVER_JAVA_BYTECODE_JAVA_TYPES_H From 055f515bd47004a6f12a898d1c3d2f1486078932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Fri, 10 Mar 2017 15:43:40 +0100 Subject: [PATCH 073/699] extend java_bytecode for test-gen-support --- .../java_bytecode_convert_method.cpp | 59 ++ src/java_bytecode/java_bytecode_language.cpp | 1 - src/java_bytecode/java_bytecode_language.h | 2 +- src/java_bytecode/java_entry_point.cpp | 5 +- src/java_bytecode/java_entry_point.h | 2 +- src/java_bytecode/java_object_factory.cpp | 516 ++++++++++++------ src/util/Makefile | 2 +- src/util/nondet_bool.h | 34 ++ src/util/nondet_ifthenelse.cpp | 134 +++++ src/util/nondet_ifthenelse.h | 44 ++ 10 files changed, 627 insertions(+), 172 deletions(-) create mode 100644 src/util/nondet_bool.h create mode 100644 src/util/nondet_ifthenelse.cpp create mode 100644 src/util/nondet_ifthenelse.h diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 447b5dacb80..e0ffe460f77 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -54,6 +54,56 @@ class patternt const char *p; }; +/*******************************************************************\ + +Function: assign_parameter_names + + Inputs: `ftype`: Function type whose parameters should be named + `name_prefix`: Prefix for parameter names, typically the + parent function's name. + `symbol_table`: Global symbol table + + Outputs: Assigns parameter names (side-effects on `ftype`) to + function stub parameters, which are initially nameless + as method conversion hasn't happened. + Also creates symbols in `symbol_table`. + + Purpose: See above + +\*******************************************************************/ + +void assign_parameter_names( + code_typet &ftype, + const irep_idt &name_prefix, + symbol_tablet &symbol_table) +{ + code_typet::parameterst ¶meters=ftype.parameters(); + + // Mostly borrowed from java_bytecode_convert.cpp; maybe factor this out. + // assign names to parameters + for(std::size_t i=0; i #include #include +#include +#include #include #include @@ -24,18 +26,6 @@ Author: Daniel Kroening, kroening@kroening.com #include "java_types.h" #include "java_utils.h" -/*******************************************************************\ - -Function: gen_nondet_init - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - class java_object_factoryt:public messaget { code_blockt &init_code; @@ -43,8 +33,18 @@ class java_object_factoryt:public messaget bool assume_non_null; size_t max_nondet_array_length; symbol_tablet &symbol_table; - message_handlert &message_handler; namespacet ns; + const source_locationt &loc; + + void set_null( + const exprt &expr, + const pointer_typet &ptr_type); + + void gen_pointer_target_init( + const exprt &expr, + const typet &target_type, + bool create_dynamic_objects, + update_in_placet update_in_place); public: java_object_factoryt( @@ -52,38 +52,40 @@ class java_object_factoryt:public messaget bool _assume_non_null, size_t _max_nondet_array_length, symbol_tablet &_symbol_table, - message_handlert &_message_handler): + message_handlert &_message_handler, + const source_locationt &_loc): + messaget(_message_handler), init_code(_init_code), assume_non_null(_assume_non_null), max_nondet_array_length(_max_nondet_array_length), symbol_table(_symbol_table), - message_handler(_message_handler), - ns(_symbol_table) + ns(_symbol_table), + loc(_loc) {} exprt allocate_object( const exprt &, const typet &, - const source_locationt &, bool create_dynamic_objects); - void gen_nondet_array_init(const exprt &expr, const source_locationt &); + void gen_nondet_array_init( + const exprt &expr, + update_in_placet); void gen_nondet_init( const exprt &expr, bool is_sub, irep_idt class_identifier, - const source_locationt &loc, bool skip_classid, bool create_dynamic_objects, - bool override=false, - const typet &override_type=empty_typet()); + bool override, + const typet &override_type, + update_in_placet); }; - /*******************************************************************\ -Function: gen_nondet_array_init +Function: java_object_factoryt::allocate_object Inputs: the target expression, desired object type, source location and Boolean whether to create a dynamic object @@ -99,7 +101,6 @@ Function: gen_nondet_array_init exprt java_object_factoryt::allocate_object( const exprt &target_expr, const typet &allocate_type, - const source_locationt &loc, bool create_dynamic_objects) { const typet &allocate_type_resolved=ns.follow(allocate_type); @@ -162,19 +163,142 @@ exprt java_object_factoryt::allocate_object( } } -// Override type says to ignore the LHS' real type, and init it with the given -// type regardless. Used at the moment for reference arrays, which are -// implemented as void* arrays but should be init'd as their true type with -// appropriate casts. +/*******************************************************************\ + +Function: java_object_factoryt::set_null + + Inputs: `expr`: pointer-typed lvalue expression to initialise + `ptr_type`: pointer type to write + + Outputs: + + Purpose: Adds an instruction to `init_code` null-initialising + `expr`. + +\*******************************************************************/ + +void java_object_factoryt::set_null( + const exprt &expr, + const pointer_typet &ptr_type) +{ + null_pointer_exprt null_pointer_expr(ptr_type); + code_assignt code(expr, null_pointer_expr); + code.add_source_location()=loc; + init_code.move_to_operands(code); +} + +/*******************************************************************\ + +Function: java_object_factoryt::gen_pointer_target_init + + Inputs: `expr`: pointer-typed lvalue expression to initialise + `target_type`: structure type to initialise, which may + not match *expr (for example, expr might be void*) + `create_dynamic_objects`: if true, use malloc to allocate + objects; otherwise generate fresh static symbols. + `update_in_place`: + NO_UPDATE_IN_PLACE: initialise `expr` from scratch + MUST_UPDATE_IN_PLACE: reinitialise an existing object + MAY_UPDATE_IN_PLACE: invalid input + + Outputs: + + Purpose: Initialises an object tree rooted at `expr`, allocating + child objects as necessary and nondet-initialising their + members, or if MUST_UPDATE_IN_PLACE is set, re-initialising + already-allocated objects. + +\*******************************************************************/ + +void java_object_factoryt::gen_pointer_target_init( + const exprt &expr, + const typet &target_type, + bool create_dynamic_objects, + update_in_placet update_in_place) +{ + assert(update_in_place!=MAY_UPDATE_IN_PLACE); + + if(target_type.id()==ID_struct && + has_prefix( + id2string(to_struct_type(target_type).get_tag()), + "java::array[")) + { + gen_nondet_array_init( + expr, + update_in_place); + } + else + { + exprt target; + if(update_in_place==NO_UPDATE_IN_PLACE) + { + target=allocate_object( + expr, + target_type, + create_dynamic_objects); + } + else + { + target=expr; + } + exprt init_expr; + if(target.id()==ID_address_of) + init_expr=target.op0(); + else + init_expr= + dereference_exprt(target, target.type().subtype()); + gen_nondet_init( + init_expr, + false, + "", + false, + create_dynamic_objects, + false, + typet(), + update_in_place); + } +} + +/*******************************************************************\ + +Function: java_object_factoryt::gen_nondet_init + + Inputs: `expr`: lvalue expression to initialise + `is_sub`: If true, `expr` is a substructure of a larger + object, which in Java necessarily means a base class. + not match *expr (for example, expr might be void*) + `class_identifier`: clsid to initialise @java.lang.Object. + @class_identifier + `skip_classid`: if true, skip initialising @class_identifier + `create_dynamic_objects`: if true, use malloc to allocate + objects; otherwise generate fresh static symbols. + `override`: If true, initialise with `override_type` instead + of `expr.type()` + `override_type`: Override type per above + `update_in_place`: + NO_UPDATE_IN_PLACE: initialise `expr` from scratch + MUST_UPDATE_IN_PLACE: reinitialise an existing object + MAY_UPDATE_IN_PLACE: generate a runtime nondet branch + between the NO_ and MUST_ cases. + + Outputs: + + Purpose: Initialises a primitive or object tree rooted at `expr`, + allocating child objects as necessary and nondet-initialising + their members, or if MUST_UPDATE_IN_PLACE is set, + re-initialising already-allocated objects. + +\*******************************************************************/ + void java_object_factoryt::gen_nondet_init( const exprt &expr, bool is_sub, irep_idt class_identifier, - const source_locationt &loc, bool skip_classid, bool create_dynamic_objects, bool override, - const typet &override_type) + const typet &override_type, + update_in_placet update_in_place) { const typet &type= override ? ns.follow(override_type) : ns.follow(expr.type()); @@ -193,79 +317,76 @@ void java_object_factoryt::gen_nondet_init( if(recursion_set.find(struct_tag)!=recursion_set.end() && struct_tag==class_identifier) { - // make null - null_pointer_exprt null_pointer_expr(pointer_type); - code_assignt code(expr, null_pointer_expr); - code.add_source_location()=loc; - init_code.copy_to_operands(code); - + if(update_in_place==NO_UPDATE_IN_PLACE) + set_null(expr, pointer_type); + // Otherwise leave it as it is. return; } } - code_labelt set_null_label; - code_labelt init_done_label; - - static size_t synthetic_constructor_count=0; + nondet_ifthenelset update_in_place_diamond( + init_code, + symbol_table, + loc, + ID_java, + "nondet_update_in_place"); - if(!assume_non_null) + if(update_in_place==MAY_UPDATE_IN_PLACE || + update_in_place==MUST_UPDATE_IN_PLACE) { - auto returns_null_sym= - new_tmp_symbol(symbol_table, "opaque_returns_null"); - returns_null_sym.type=c_bool_typet(1); - auto returns_null=returns_null_sym.symbol_expr(); - auto assign_returns_null= - code_assignt(returns_null, get_nondet_bool(returns_null_sym.type)); - assign_returns_null.add_source_location()=loc; - init_code.move_to_operands(assign_returns_null); + if(update_in_place==MAY_UPDATE_IN_PLACE) + update_in_place_diamond.begin_if(); + + // If we're trying to update an object in place + // but it is null, just leave it alone. + static unsigned long null_check_count=0; + std::ostringstream oss; + oss << "null_check_failed_" << (++null_check_count); + code_labelt post_null_check(oss.str(), code_skipt()); + code_ifthenelset null_check; + null_check.cond()=equal_exprt(expr, null_pointer_exprt(pointer_type)); + null_check.then_case()=code_gotot(post_null_check.get_label()); + init_code.move_to_operands(null_check); - auto set_null_inst= - code_assignt(expr, null_pointer_exprt(pointer_type)); - set_null_inst.add_source_location()=loc; + gen_pointer_target_init( + expr, + subtype, + create_dynamic_objects, + MUST_UPDATE_IN_PLACE); - std::string fresh_label= - "post_synthetic_malloc_"+std::to_string(++synthetic_constructor_count); - set_null_label=code_labelt(fresh_label, set_null_inst); + init_code.move_to_operands(post_null_check); - init_done_label=code_labelt(fresh_label+"_init_done", code_skipt()); + if(update_in_place==MUST_UPDATE_IN_PLACE) + return; - code_ifthenelset null_check; - exprt null_return= - zero_initializer(returns_null_sym.type, loc, ns, message_handler); - null_check.cond()= - notequal_exprt(returns_null, null_return); - null_check.then_case()=code_gotot(fresh_label); - init_code.move_to_operands(null_check); + update_in_place_diamond.begin_else(); } - if(java_is_array_type(subtype)) - gen_nondet_array_init(expr, loc); - else - { - exprt allocated= - allocate_object(expr, subtype, loc, create_dynamic_objects); - { - exprt init_expr; - if(allocated.id()==ID_address_of) - init_expr=allocated.op0(); - else - init_expr=dereference_exprt(allocated, allocated.type().subtype()); - gen_nondet_init( - init_expr, - false, - "", - loc, - false, - create_dynamic_objects); - } - } + nondet_ifthenelset init_null_diamond( + init_code, + symbol_table, + loc, + ID_java, + "nondet_ptr_is_null"); if(!assume_non_null) { - init_code.copy_to_operands(code_gotot(init_done_label.get_label())); - init_code.move_to_operands(set_null_label); - init_code.move_to_operands(init_done_label); + init_null_diamond.begin_if(); + set_null(expr, pointer_type); + init_null_diamond.begin_else(); } + + gen_pointer_target_init( + expr, + subtype, + create_dynamic_objects, + NO_UPDATE_IN_PLACE); + + if(!assume_non_null) + init_null_diamond.finish(); + + if(update_in_place==MAY_UPDATE_IN_PLACE) + update_in_place_diamond.finish(); } else if(type.id()==ID_struct) { @@ -291,7 +412,7 @@ void java_object_factoryt::gen_nondet_init( if(name=="@class_identifier") { - if(skip_classid) + if(skip_classid || update_in_place==MUST_UPDATE_IN_PLACE) continue; irep_idt qualified_clsid="java::"+as_string(class_identifier); @@ -302,6 +423,8 @@ void java_object_factoryt::gen_nondet_init( } else if(name=="@lock") { + if(update_in_place==MUST_UPDATE_IN_PLACE) + continue; code_assignt code(me, from_integer(0, me.type())); code.add_source_location()=loc; init_code.copy_to_operands(code); @@ -316,13 +439,22 @@ void java_object_factoryt::gen_nondet_init( _is_sub?(class_identifier.empty()?struct_tag:class_identifier):""; #endif + // MUST_UPDATE_IN_PLACE only applies to this object. + // If this is a pointer to another object, offer the chance + // to leave it alone by setting MAY_UPDATE_IN_PLACE instead. + update_in_placet substruct_in_place= + update_in_place==MUST_UPDATE_IN_PLACE && !_is_sub ? + MAY_UPDATE_IN_PLACE : + update_in_place; gen_nondet_init( me, _is_sub, class_identifier, - loc, false, - create_dynamic_objects); + create_dynamic_objects, + false, + typet(), + substruct_in_place); } } recursion_set.erase(struct_tag); @@ -339,23 +471,28 @@ void java_object_factoryt::gen_nondet_init( /*******************************************************************\ -Function: gen_nondet_array_init - - Inputs: +Function: java_object_factoryt::gen_nondet_array_init + Inputs: `expr`: Array-typed expression to initialise + `update_in_place`: + NO_UPDATE_IN_PLACE: initialise `expr` from scratch + MUST_UPDATE_IN_PLACE: reinitialise an existing array + MAY_UPDATE_IN_PLACE: invalid input Outputs: Purpose: create code to initialize a Java array with size `max_nondet_array_length`, loop over elements and initialize - them + or reinitialize them \*******************************************************************/ void java_object_factoryt::gen_nondet_array_init( const exprt &expr, - const source_locationt &loc) + update_in_placet update_in_place) { + assert(update_in_place!=MAY_UPDATE_IN_PLACE); assert(expr.type().id()==ID_pointer); + const typet &type=ns.follow(expr.type().subtype()); const struct_typet &struct_type=to_struct_type(type); assert(expr.type().subtype().id()==ID_symbol); @@ -365,35 +502,58 @@ void java_object_factoryt::gen_nondet_array_init( auto max_length_expr=from_integer(max_nondet_array_length, java_int_type()); typet allocate_type; - symbolt &length_sym=new_tmp_symbol(symbol_table, "nondet_array_length"); - length_sym.type=java_int_type(); - const auto &length_sym_expr=length_sym.symbol_expr(); - - // Initialize array with some undetermined length: - gen_nondet_init(length_sym_expr, false, irep_idt(), loc, false, false); - - // Insert assumptions to bound its length: - binary_relation_exprt - assume1(length_sym_expr, ID_ge, from_integer(0, java_int_type())); - binary_relation_exprt - assume2(length_sym_expr, ID_le, max_length_expr); - code_assumet assume_inst1(assume1); - code_assumet assume_inst2(assume2); - init_code.move_to_operands(assume_inst1); - init_code.move_to_operands(assume_inst2); - - side_effect_exprt java_new_array(ID_java_new_array, expr.type()); - java_new_array.copy_to_operands(length_sym_expr); - java_new_array.type().subtype().set(ID_C_element_type, element_type); - codet assign=code_assignt(expr, java_new_array); - assign.add_source_location()=loc; - init_code.copy_to_operands(assign); - - exprt init_array_expr= - member_exprt( - dereference_exprt(expr, expr.type().subtype()), - "data", - struct_type.components()[2].type()); + exprt length_sym_expr; + + if(update_in_place==NO_UPDATE_IN_PLACE) + { + symbolt &length_sym=new_tmp_symbol(symbol_table, "nondet_array_length"); + length_sym.type=java_int_type(); + length_sym_expr=length_sym.symbol_expr(); + + // Initialise array with some undetermined length: + gen_nondet_init( + length_sym_expr, + false, + irep_idt(), + false, + false, + false, + typet(), + NO_UPDATE_IN_PLACE); + + // Insert assumptions to bound its length: + binary_relation_exprt assume1(length_sym_expr, ID_ge, + from_integer(0, java_int_type())); + binary_relation_exprt assume2(length_sym_expr, ID_le, + max_length_expr); + + code_assumet assume_inst1(assume1); + code_assumet assume_inst2(assume2); + init_code.move_to_operands(assume_inst1); + init_code.move_to_operands(assume_inst2); + + side_effect_exprt java_new_array(ID_java_new_array, expr.type()); + java_new_array.copy_to_operands(length_sym_expr); + java_new_array.set(ID_skip_initialize, true); + java_new_array.type().subtype().set(ID_C_element_type, element_type); + codet assign=code_assignt(expr, java_new_array); + assign.add_source_location()=loc; + init_code.copy_to_operands(assign); + } + else + { + // Update in place. Get existing array length: + length_sym_expr= + member_exprt( + dereference_exprt(expr, expr.type().subtype()), + "length", + struct_type.component_type("length")); + } + + exprt init_array_expr=member_exprt( + dereference_exprt(expr, expr.type().subtype()), + "data", + struct_type.component_type("data")); if(init_array_expr.type()!=pointer_typet(element_type)) init_array_expr= typecast_exprt(init_array_expr, pointer_typet(element_type)); @@ -432,27 +592,36 @@ void java_object_factoryt::gen_nondet_array_init( init_code.move_to_operands(done_test); - // Add a redundant if(counter == max_length) break that is easier for the - // unwinder to understand. - code_ifthenelset max_test; - max_test.cond()=equal_exprt(counter_expr, max_length_expr); - max_test.then_case()=goto_done; - - init_code.move_to_operands(max_test); + if(update_in_place!=MUST_UPDATE_IN_PLACE) + { + // Add a redundant if(counter == max_length) break + // that is easier for the unwinder to understand. + code_ifthenelset max_test; + max_test.cond()=equal_exprt(counter_expr, max_length_expr); + max_test.then_case()=goto_done; + init_code.move_to_operands(max_test); + } exprt arraycellref=dereference_exprt( plus_exprt(array_init_symexpr, counter_expr, array_init_symexpr.type()), array_init_symexpr.type().subtype()); + // MUST_UPDATE_IN_PLACE only applies to this object. + // If this is a pointer to another object, offer the chance + // to leave it alone by setting MAY_UPDATE_IN_PLACE instead. + update_in_placet child_update_in_place= + update_in_place==MUST_UPDATE_IN_PLACE ? + MAY_UPDATE_IN_PLACE : + update_in_place; gen_nondet_init( arraycellref, false, irep_idt(), - loc, false, true, true, - element_type); + element_type, + child_update_in_place); exprt java_one=from_integer(1, java_int_type()); code_assignt incr(counter_expr, plus_exprt(counter_expr, java_one)); @@ -466,11 +635,32 @@ void java_object_factoryt::gen_nondet_array_init( Function: gen_nondet_init - Inputs: - - Outputs: - - Purpose: + Inputs: `expr`: lvalue expression to initialise + `loc`: source location for all generated code + `skip_classid`: if true, skip initialising @class_identifier + `create_dyn_objs`: if true, use malloc to allocate + objects; otherwise generate fresh static symbols. + `assume_non_null`: never initialise pointer members with + null, unless forced to by recursive datatypes + `message_handler`: logging + `max_nondet_array_length`: upper bound on size of initialised + arrays. + `update_in_place`: + NO_UPDATE_IN_PLACE: initialise `expr` from scratch + MUST_UPDATE_IN_PLACE: reinitialise an existing object + MAY_UPDATE_IN_PLACE: generate a runtime nondet branch + between the NO_ and MUST_ cases. + + Outputs: `init_code` gets an instruction sequence to initialise or + reinitialise `expr` and child objects it refers to. + `symbol_table` is modified with any new symbols created. This + includes any necessary temporaries, and if `create_dyn_objs` + is false, any allocated objects. + + Purpose: Initialises a primitive or object tree rooted at `expr`, + allocating child objects as necessary and nondet-initialising + their members, or if MAY_ or MUST_UPDATE_IN_PLACE is set, + re-initialising already-allocated objects. \*******************************************************************/ @@ -491,23 +681,27 @@ void gen_nondet_init( assume_non_null, max_nondet_array_length, symbol_table, - message_handler); + message_handler, + loc); state.gen_nondet_init( expr, false, "", - loc, skip_classid, - create_dyn_objs); + create_dyn_objs, + false, + typet(), + update_in_place); } /*******************************************************************\ Function: new_tmp_symbol - Inputs: + Inputs: `prefix`: new symbol name prefix - Outputs: + Outputs: A fresh-named symbol is added to `symbol_table` and also + returned. Purpose: @@ -533,32 +727,23 @@ symbolt &new_tmp_symbol(symbol_tablet &symbol_table, const std::string &prefix) /*******************************************************************\ -Function: get_nondet_bool - - Inputs: Desired type (C_bool or plain bool) - - Outputs: nondet expr of that type - - Purpose: - -\*******************************************************************/ - -exprt get_nondet_bool(const typet &type) -{ - // We force this to 0 and 1 and won't consider - // other values. - return typecast_exprt(side_effect_expr_nondett(bool_typet()), type); -} - -/*******************************************************************\ - Function: object_factory - Inputs: + Inputs: `type`: type of new object to create + `allow_null`: if true, may return null; otherwise always + allocates an object + `max_nondet_array_length`: upper bound on size of initialised + arrays. + `loc`: source location for all generated code + `message_handler`: logging - Outputs: + Outputs: `symbol_table` gains any new symbols created, as per + gen_nondet_init above. + `init_code` gains any instructions requried to initialise + either the returned value or its child objects - Purpose: + Purpose: Similar to `gen_nondet_init` above, but always creates a + fresh static global object or primitive nondet expression. \*******************************************************************/ @@ -579,7 +764,6 @@ exprt object_factory( exprt object=aux_symbol.symbol_expr(); - const namespacet ns(symbol_table); gen_nondet_init( object, init_code, diff --git a/src/util/Makefile b/src/util/Makefile index c605d26c747..4cacd3dbc0f 100644 --- a/src/util/Makefile +++ b/src/util/Makefile @@ -22,7 +22,7 @@ SRC = arith_tools.cpp base_type.cpp cmdline.cpp config.cpp symbol_table.cpp \ irep_ids.cpp byte_operators.cpp string2int.cpp file_util.cpp \ memory_info.cpp pipe_stream.cpp irep_hash.cpp endianness_map.cpp \ ssa_expr.cpp json_irep.cpp json_expr.cpp \ - format_number_range.cpp string_utils.cpp + format_number_range.cpp string_utils.cpp nondet_ifthenelse.cpp INCLUDES= -I .. diff --git a/src/util/nondet_bool.h b/src/util/nondet_bool.h new file mode 100644 index 00000000000..6aee700b889 --- /dev/null +++ b/src/util/nondet_bool.h @@ -0,0 +1,34 @@ +/*******************************************************************\ + +Module: Nondeterministic boolean helper + +Author: Chris Smowton, chris@smowton.net + +\*******************************************************************/ + +#ifndef CPROVER_UTIL_NONDET_BOOL_H +#define CPROVER_UTIL_NONDET_BOOL_H + +#include +#include + +/*******************************************************************\ + +Function: get_nondet_bool + + Inputs: Desired type (C_bool or plain bool) + + Outputs: nondet expr of that type + + Purpose: + +\*******************************************************************/ + +inline exprt get_nondet_bool(const typet &type) +{ + // We force this to 0 and 1 and won't consider + // other values. + return typecast_exprt(side_effect_expr_nondett(bool_typet()), type); +} + +#endif // CPROVER_UTIL_NONDET_BOOL_H diff --git a/src/util/nondet_ifthenelse.cpp b/src/util/nondet_ifthenelse.cpp new file mode 100644 index 00000000000..ae2f9040977 --- /dev/null +++ b/src/util/nondet_ifthenelse.cpp @@ -0,0 +1,134 @@ +/*******************************************************************\ + +Module: Nondeterministic if-then-else + +Author: Chris Smowton, chris@smowton.net + +\*******************************************************************/ + +#include "nondet_ifthenelse.h" + +#include + +#include +#include +#include +#include +#include +#include + +// This will be unified with other similar fresh-symbol routines shortly +static symbolt &new_tmp_symbol( + symbol_tablet &symbol_table, + const std::string &prefix, + const irep_idt &mode) +{ + static size_t temporary_counter=0; + + auxiliary_symbolt new_symbol; + symbolt *symbol_ptr; + + do + { + new_symbol.name="tmp_object_factory$"+std::to_string(++temporary_counter); + new_symbol.base_name=new_symbol.name; + new_symbol.mode=mode; + } + while(symbol_table.move(new_symbol, symbol_ptr)); + + return *symbol_ptr; +} + +/*******************************************************************\ + +Function: nondet_ifthenelset::begin_if + + Inputs: + + Outputs: + + Purpose: Emits instructions and defines labels for the beginning of + a nondeterministic if-else diamond. Code is emitted to the + `result_code` member of this object's associated + `java_object_factoryt` instance `state`. + The caller should use the following pattern (where *this + is an instance of java_object_factoryt): + ``` + nondet_ifthenelset diamond(*this, "name"); + diamond.begin_if(); + result_code.copy_to_operands(Some if-branch code) + diamond.begin_else(); + result_code.copy_to_operands(Some else-branch code) + diamond.finish(); + ``` + +\*******************************************************************/ + +void nondet_ifthenelset::begin_if() +{ + static size_t nondet_ifthenelse_count=0; + + auto choice_sym= + new_tmp_symbol(symbol_table, choice_symname, fresh_symbol_mode); + choice_sym.type=c_bool_typet(1); + auto choice=choice_sym.symbol_expr(); + auto assign_choice= + code_assignt(choice, get_nondet_bool(choice_sym.type)); + assign_choice.add_source_location()=loc; + result_code.move_to_operands(assign_choice); + + std::ostringstream fresh_label_oss; + fresh_label_oss << choice_symname << "_else_" + << (++nondet_ifthenelse_count); + std::string fresh_label=fresh_label_oss.str(); + else_label=code_labelt(fresh_label, code_skipt()); + + std::ostringstream done_label_oss; + done_label_oss << choice_symname << "_done_" + << nondet_ifthenelse_count; + join_label=code_labelt(done_label_oss.str(), code_skipt()); + + code_ifthenelset test; + test.cond()=equal_exprt( + choice, + constant_exprt("0", choice_sym.type)); + test.then_case()=code_gotot(fresh_label); + result_code.move_to_operands(test); +} + +/*******************************************************************\ + +Function: nondet_ifthenelset::begin_else + + Inputs: + + Outputs: + + Purpose: Terminates the if-block and begins the else-block of a + nondet if-then-else diamond. See ::begin_if for detail. + +\*******************************************************************/ + +void nondet_ifthenelset::begin_else() +{ + result_code.copy_to_operands(code_gotot(join_label.get_label())); + result_code.copy_to_operands(else_label); +} + +/*******************************************************************\ + +Function: nondet_ifthenelset::finish + + Inputs: + + Outputs: + + Purpose: Concludes a nondet if-then-else diamond. + See ::begin_if for detail. + +\*******************************************************************/ + +void nondet_ifthenelset::finish() +{ + result_code.move_to_operands(join_label); +} diff --git a/src/util/nondet_ifthenelse.h b/src/util/nondet_ifthenelse.h new file mode 100644 index 00000000000..c6ee25afcab --- /dev/null +++ b/src/util/nondet_ifthenelse.h @@ -0,0 +1,44 @@ +/*******************************************************************\ + +Module: Nondeterministic if-then-else + +Author: Chris Smowton, chris@smowton.net + +\*******************************************************************/ + +#ifndef CPROVER_UTIL_NONDET_IFTHENELSE_H +#define CPROVER_UTIL_NONDET_IFTHENELSE_H + +#include + +class symbol_tablet; +class source_locationt; + +class nondet_ifthenelset +{ + code_blockt &result_code; + symbol_tablet &symbol_table; + const source_locationt &loc; + irep_idt fresh_symbol_mode; + code_labelt else_label; + code_labelt join_label; + const std::string choice_symname; + public: + nondet_ifthenelset( + code_blockt &_result_code, + symbol_tablet &_symbol_table, + const source_locationt &_loc, + const irep_idt &_fresh_symbol_mode, + const std::string &name) : + result_code(_result_code), + symbol_table(_symbol_table), + loc(_loc), + fresh_symbol_mode(_fresh_symbol_mode), + choice_symname(name) + {} + void begin_if(); + void begin_else(); + void finish(); +}; + +#endif // CPROVER_UTIL_NONDET_IFTHENELSE_H From ae5282bdfc40e1fa2286148d9fea797f3ce5319f Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Fri, 2 Sep 2016 16:28:21 +0100 Subject: [PATCH 074/699] generate goals only if they do not exist in the json file --- src/goto-instrument/cover.cpp | 54 ++++++++++++++++++++++++++++--- src/goto-instrument/cover.h | 16 +++++++-- src/symex/symex_parse_options.cpp | 3 +- 3 files changed, 66 insertions(+), 7 deletions(-) diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index 9f1aa347679..b66e4f6f718 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -96,6 +96,47 @@ class basic_blockst } }; +/*******************************************************************\ + +Function: coverage_goals::set_goals + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void coverage_goals::set_goals(std::string goal) +{ + existing_goals.push_back(goal); +} + +/*******************************************************************\ + +Function: coverage_goals::get_goals + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +const bool coverage_goals::get_goals(const char* goal) +{ + std::vector::iterator it; + it = find (existing_goals.begin(), existing_goals.end(), goal); + + if(it == existing_goals.end()) + return true; + else + return false; +} + + /*******************************************************************\ Function: as_string @@ -1108,7 +1149,8 @@ Function: instrument_cover_goals void instrument_cover_goals( const symbol_tablet &symbol_table, goto_programt &goto_program, - coverage_criteriont criterion) + coverage_criteriont criterion, + coverage_goals &goals) { const namespacet ns(symbol_table); basic_blockst basic_blocks(goto_program); @@ -1176,7 +1218,9 @@ void instrument_cover_goals( source_locationt source_location= basic_blocks.source_location_map[block_nr]; - if(!source_location.get_file().empty() && + //check whether the current goal already exists + if(goals.get_goals(source_location.get_line().c_str()) && + !source_location.get_file().empty() && source_location.get_file()[0]!='<') { std::string comment="block "+b; @@ -1426,7 +1470,8 @@ Function: instrument_cover_goals void instrument_cover_goals( const symbol_tablet &symbol_table, goto_functionst &goto_functions, - coverage_criteriont criterion) + coverage_criteriont criterion, + coverage_goals &goals) { Forall_goto_functions(f_it, goto_functions) { @@ -1437,6 +1482,7 @@ void instrument_cover_goals( instrument_cover_goals( symbol_table, f_it->second.body, - criterion); + criterion, + goals); } } diff --git a/src/goto-instrument/cover.h b/src/goto-instrument/cover.h index e897c88b753..d301e48880f 100644 --- a/src/goto-instrument/cover.h +++ b/src/goto-instrument/cover.h @@ -13,6 +13,16 @@ Date: May 2016 #include +class coverage_goals +{ +public: + void set_goals(std::string goal); + const bool get_goals(const char* goal); + +private: + std::vector existing_goals; +}; + enum class coverage_criteriont { LOCATION, BRANCH, DECISION, CONDITION, @@ -21,11 +31,13 @@ enum class coverage_criteriont void instrument_cover_goals( const symbol_tablet &symbol_table, goto_programt &goto_program, - coverage_criteriont); + coverage_criteriont, + coverage_goals &goals); void instrument_cover_goals( const symbol_tablet &symbol_table, goto_functionst &goto_functions, - coverage_criteriont); + coverage_criteriont, + coverage_goals &goals); #endif // CPROVER_GOTO_INSTRUMENT_COVER_H diff --git a/src/symex/symex_parse_options.cpp b/src/symex/symex_parse_options.cpp index 518e64a2ecd..bbae2056513 100644 --- a/src/symex/symex_parse_options.cpp +++ b/src/symex/symex_parse_options.cpp @@ -409,7 +409,8 @@ bool symex_parse_optionst::process_goto_program(const optionst &options) } status() << "Instrumenting coverge goals" << eom; - instrument_cover_goals(symbol_table, goto_model.goto_functions, c); + coverage_goals goals; + instrument_cover_goals(symbol_table, goto_model.goto_functions, c, goals); goto_model.goto_functions.update(); } From ead4b237a00c7e76d9c6c3707f5d008fe0f0fe58 Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Mon, 5 Sep 2016 13:14:51 +0100 Subject: [PATCH 075/699] add more test cases to check existing coverage --- src/goto-instrument/cover.cpp | 16 ++++++++-------- src/goto-instrument/cover.h | 12 ++++++------ src/symex/symex_parse_options.cpp | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index b66e4f6f718..e5d0042bcb5 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -98,7 +98,7 @@ class basic_blockst /*******************************************************************\ -Function: coverage_goals::set_goals +Function: coverage_goalst::set_goals Inputs: @@ -108,14 +108,14 @@ Function: coverage_goals::set_goals \*******************************************************************/ -void coverage_goals::set_goals(std::string goal) +void coverage_goalst::set_goals(std::string goal) { existing_goals.push_back(goal); } /*******************************************************************\ -Function: coverage_goals::get_goals +Function: coverage_goalst::is_existing_goal Inputs: @@ -125,7 +125,7 @@ Function: coverage_goals::get_goals \*******************************************************************/ -const bool coverage_goals::get_goals(const char* goal) +bool coverage_goalst::is_existing_goal(const char* goal) { std::vector::iterator it; it = find (existing_goals.begin(), existing_goals.end(), goal); @@ -133,7 +133,7 @@ const bool coverage_goals::get_goals(const char* goal) if(it == existing_goals.end()) return true; else - return false; + return false; } @@ -1150,7 +1150,7 @@ void instrument_cover_goals( const symbol_tablet &symbol_table, goto_programt &goto_program, coverage_criteriont criterion, - coverage_goals &goals) + coverage_goalst &goals) { const namespacet ns(symbol_table); basic_blockst basic_blocks(goto_program); @@ -1219,7 +1219,7 @@ void instrument_cover_goals( basic_blocks.source_location_map[block_nr]; //check whether the current goal already exists - if(goals.get_goals(source_location.get_line().c_str()) && + if(goals.is_existing_goal(source_location.get_line().c_str()) && !source_location.get_file().empty() && source_location.get_file()[0]!='<') { @@ -1471,7 +1471,7 @@ void instrument_cover_goals( const symbol_tablet &symbol_table, goto_functionst &goto_functions, coverage_criteriont criterion, - coverage_goals &goals) + coverage_goalst &goals) { Forall_goto_functions(f_it, goto_functions) { diff --git a/src/goto-instrument/cover.h b/src/goto-instrument/cover.h index d301e48880f..623dd4387f9 100644 --- a/src/goto-instrument/cover.h +++ b/src/goto-instrument/cover.h @@ -13,14 +13,14 @@ Date: May 2016 #include -class coverage_goals +class coverage_goalst { public: - void set_goals(std::string goal); - const bool get_goals(const char* goal); + void set_goals(std::string goal); + bool is_existing_goal(const char* goal); private: - std::vector existing_goals; + std::vector existing_goals; }; enum class coverage_criteriont @@ -32,12 +32,12 @@ void instrument_cover_goals( const symbol_tablet &symbol_table, goto_programt &goto_program, coverage_criteriont, - coverage_goals &goals); + coverage_goalst &goals); void instrument_cover_goals( const symbol_tablet &symbol_table, goto_functionst &goto_functions, coverage_criteriont, - coverage_goals &goals); + coverage_goalst &goals); #endif // CPROVER_GOTO_INSTRUMENT_COVER_H diff --git a/src/symex/symex_parse_options.cpp b/src/symex/symex_parse_options.cpp index bbae2056513..d1343da3eb3 100644 --- a/src/symex/symex_parse_options.cpp +++ b/src/symex/symex_parse_options.cpp @@ -409,7 +409,7 @@ bool symex_parse_optionst::process_goto_program(const optionst &options) } status() << "Instrumenting coverge goals" << eom; - coverage_goals goals; + coverage_goalst goals; instrument_cover_goals(symbol_table, goto_model.goto_functions, c, goals); goto_model.goto_functions.update(); } From b128a597e5f9bb8a795688586bff60068cae3f3b Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Tue, 6 Sep 2016 10:11:28 +0100 Subject: [PATCH 076/699] default variant of instrument_cover_goals that uses an empty set of existing goals Signed-off-by: Lucas Cordeiro --- src/goto-instrument/cover.cpp | 30 ++++++++++++++++++++++++++++++ src/goto-instrument/cover.h | 5 +++++ src/symex/symex_parse_options.cpp | 3 +-- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index e5d0042bcb5..a33c7f462eb 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -1486,3 +1486,33 @@ void instrument_cover_goals( goals); } } + +/*******************************************************************\ + +Function: instrument_cover_goals + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void instrument_cover_goals( + const symbol_tablet &symbol_table, + goto_functionst &goto_functions, + coverage_criteriont criterion) +{ + Forall_goto_functions(f_it, goto_functions) + { + if(f_it->first==ID__start || + f_it->first=="__CPROVER_initialize") + continue; + + //empty set of existing goals + coverage_goalst goals; + instrument_cover_goals(symbol_table, f_it->second.body, + criterion, goals); + } +} diff --git a/src/goto-instrument/cover.h b/src/goto-instrument/cover.h index 623dd4387f9..547cef5b19c 100644 --- a/src/goto-instrument/cover.h +++ b/src/goto-instrument/cover.h @@ -40,4 +40,9 @@ void instrument_cover_goals( coverage_criteriont, coverage_goalst &goals); +void instrument_cover_goals( + const symbol_tablet &symbol_table, + goto_functionst &goto_functions, + coverage_criteriont); + #endif // CPROVER_GOTO_INSTRUMENT_COVER_H diff --git a/src/symex/symex_parse_options.cpp b/src/symex/symex_parse_options.cpp index d1343da3eb3..518e64a2ecd 100644 --- a/src/symex/symex_parse_options.cpp +++ b/src/symex/symex_parse_options.cpp @@ -409,8 +409,7 @@ bool symex_parse_optionst::process_goto_program(const optionst &options) } status() << "Instrumenting coverge goals" << eom; - coverage_goalst goals; - instrument_cover_goals(symbol_table, goto_model.goto_functions, c, goals); + instrument_cover_goals(symbol_table, goto_model.goto_functions, c); goto_model.goto_functions.update(); } From 143b53e77fca7afde6f05f7e49e8fb7d8dd3b025 Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Tue, 6 Sep 2016 10:19:04 +0100 Subject: [PATCH 077/699] a goal should be identified by a source_locationt Signed-off-by: Lucas Cordeiro --- src/goto-instrument/cover.cpp | 7 ++++--- src/goto-instrument/cover.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index a33c7f462eb..51a35b1854b 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -125,10 +125,11 @@ Function: coverage_goalst::is_existing_goal \*******************************************************************/ -bool coverage_goalst::is_existing_goal(const char* goal) +bool coverage_goalst::is_existing_goal(source_locationt source_location) { std::vector::iterator it; - it = find (existing_goals.begin(), existing_goals.end(), goal); + it = find (existing_goals.begin(), existing_goals.end(), + source_location.get_line().c_str()); if(it == existing_goals.end()) return true; @@ -1219,7 +1220,7 @@ void instrument_cover_goals( basic_blocks.source_location_map[block_nr]; //check whether the current goal already exists - if(goals.is_existing_goal(source_location.get_line().c_str()) && + if(goals.is_existing_goal(source_location) && !source_location.get_file().empty() && source_location.get_file()[0]!='<') { diff --git a/src/goto-instrument/cover.h b/src/goto-instrument/cover.h index 547cef5b19c..cb88eee166c 100644 --- a/src/goto-instrument/cover.h +++ b/src/goto-instrument/cover.h @@ -17,7 +17,7 @@ class coverage_goalst { public: void set_goals(std::string goal); - bool is_existing_goal(const char* goal); + bool is_existing_goal(source_locationt source_location); private: std::vector existing_goals; From f70eadf6ce88c77a7432c433a31b1527d6bb8eec Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Tue, 6 Sep 2016 14:28:24 +0100 Subject: [PATCH 078/699] implement get_coverage method Signed-off-by: Lucas Cordeiro --- src/goto-instrument/Makefile | 1 + src/goto-instrument/cover.cpp | 58 +++++++++++++++++++++++++++++++++++ src/goto-instrument/cover.h | 2 ++ src/symex/Makefile | 1 + 4 files changed, 62 insertions(+) diff --git a/src/goto-instrument/Makefile b/src/goto-instrument/Makefile index 65cb278a7fc..df45e7612fe 100644 --- a/src/goto-instrument/Makefile +++ b/src/goto-instrument/Makefile @@ -37,6 +37,7 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \ ../langapi/langapi$(LIBEXT) \ ../xmllang/xmllang$(LIBEXT) \ ../util/util$(LIBEXT) \ + ../json/json$(LIBEXT) \ ../solvers/solvers$(LIBEXT) INCLUDES= -I .. diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index 51a35b1854b..701e7704bfc 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -16,6 +16,8 @@ Date: May 2016 #include #include +#include + #include "cover.h" class basic_blockst @@ -98,6 +100,62 @@ class basic_blockst /*******************************************************************\ +Function: coverage_goalst::get_coverage + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void coverage_goalst::get_coverage(const std::string &coverage, + message_handlert &message_handler) +{ + jsont json; + + //check coverage file + if(parse_json(coverage, message_handler, json)) + { + messaget message(message_handler); + message.error() << coverage << " file is not a valid json file" + << messaget::eom; + exit(0); + } + + //make sure that we have an array of elements + if(!json.is_array()) + { + messaget message(message_handler); + message.error() << "expecting an array in the " << coverage << " file, but got " + << json << messaget::eom; + exit(0); + } + + for(jsont::arrayt::const_iterator + it=json.array.begin(); + it!=json.array.end(); + it++) + { + //get the goals array + if ((*it)["goals"].is_array()) + { + for(jsont::arrayt::const_iterator + itg=(*it)["goals"].array.begin(); + itg!=(*it)["goals"].array.end(); + itg++) + { + //get the line of each existing goal + const std::string line=(*itg)["sourceLocation"]["line"].value; + set_goals(line); + } + } + } +} + +/*******************************************************************\ + Function: coverage_goalst::set_goals Inputs: diff --git a/src/goto-instrument/cover.h b/src/goto-instrument/cover.h index cb88eee166c..0029eeef5d4 100644 --- a/src/goto-instrument/cover.h +++ b/src/goto-instrument/cover.h @@ -16,6 +16,8 @@ Date: May 2016 class coverage_goalst { public: + void get_coverage(const std::string &coverage, + message_handlert &message_handler); void set_goals(std::string goal); bool is_existing_goal(source_locationt source_location); diff --git a/src/symex/Makefile b/src/symex/Makefile index 5a66801eec4..e3a9c677b78 100644 --- a/src/symex/Makefile +++ b/src/symex/Makefile @@ -16,6 +16,7 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \ ../goto-symex/rewrite_union$(OBJEXT) \ ../pointer-analysis/dereference$(OBJEXT) \ ../goto-instrument/cover$(OBJEXT) \ + ../json/json$(LIBEXT) \ ../path-symex/path-symex$(LIBEXT) INCLUDES= -I .. From eff4b71494c8bb32b9034786c0e51f228e880442 Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Tue, 6 Sep 2016 15:15:52 +0100 Subject: [PATCH 079/699] a goal should be identified by a source_locationt Signed-off-by: Lucas Cordeiro --- src/goto-instrument/cover.cpp | 22 +++++++++++++++------- src/goto-instrument/cover.h | 4 ++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index 701e7704bfc..4b191dbd4fa 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -8,6 +8,8 @@ Date: May 2016 \*******************************************************************/ +#include + #include #include #include @@ -114,6 +116,7 @@ void coverage_goalst::get_coverage(const std::string &coverage, message_handlert &message_handler) { jsont json; + source_locationt source_location; //check coverage file if(parse_json(coverage, message_handler, json)) @@ -133,6 +136,7 @@ void coverage_goalst::get_coverage(const std::string &coverage, exit(0); } + irep_idt line_number; for(jsont::arrayt::const_iterator it=json.array.begin(); it!=json.array.end(); @@ -147,8 +151,9 @@ void coverage_goalst::get_coverage(const std::string &coverage, itg++) { //get the line of each existing goal - const std::string line=(*itg)["sourceLocation"]["line"].value; - set_goals(line); + line_number=(*itg)["sourceLocation"]["line"].value; + source_location.set_line(line_number); + set_goals(source_location); } } } @@ -166,7 +171,7 @@ Function: coverage_goalst::set_goals \*******************************************************************/ -void coverage_goalst::set_goals(std::string goal) +void coverage_goalst::set_goals(source_locationt goal) { existing_goals.push_back(goal); } @@ -185,10 +190,13 @@ Function: coverage_goalst::is_existing_goal bool coverage_goalst::is_existing_goal(source_locationt source_location) { - std::vector::iterator it; - it = find (existing_goals.begin(), existing_goals.end(), - source_location.get_line().c_str()); - + std::vector::iterator it = existing_goals.begin(); + while (it!=existing_goals.end()) + { + if (!source_location.get_line().compare(it->get_line())) + break; + ++it; + } if(it == existing_goals.end()) return true; else diff --git a/src/goto-instrument/cover.h b/src/goto-instrument/cover.h index 0029eeef5d4..de03aa07d65 100644 --- a/src/goto-instrument/cover.h +++ b/src/goto-instrument/cover.h @@ -18,11 +18,11 @@ class coverage_goalst public: void get_coverage(const std::string &coverage, message_handlert &message_handler); - void set_goals(std::string goal); + void set_goals(source_locationt goal); bool is_existing_goal(source_locationt source_location); private: - std::vector existing_goals; + std::vector existing_goals; }; enum class coverage_criteriont From a91860a6e6a46d1bf9ae7881489ba6e9908921e0 Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Tue, 6 Sep 2016 15:44:05 +0100 Subject: [PATCH 080/699] method to construct a coverage_goalst object --- src/goto-instrument/cover.cpp | 8 ++++---- src/goto-instrument/cover.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index 4b191dbd4fa..974e3aab9ff 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -8,8 +8,6 @@ Date: May 2016 \*******************************************************************/ -#include - #include #include #include @@ -112,10 +110,11 @@ Function: coverage_goalst::get_coverage \*******************************************************************/ -void coverage_goalst::get_coverage(const std::string &coverage, +coverage_goalst coverage_goalst::get_coverage_goals(const std::string &coverage, message_handlert &message_handler) { jsont json; + coverage_goalst goals; source_locationt source_location; //check coverage file @@ -153,10 +152,11 @@ void coverage_goalst::get_coverage(const std::string &coverage, //get the line of each existing goal line_number=(*itg)["sourceLocation"]["line"].value; source_location.set_line(line_number); - set_goals(source_location); + goals.set_goals(source_location); } } } + return goals; } /*******************************************************************\ diff --git a/src/goto-instrument/cover.h b/src/goto-instrument/cover.h index de03aa07d65..6dca58da366 100644 --- a/src/goto-instrument/cover.h +++ b/src/goto-instrument/cover.h @@ -16,8 +16,8 @@ Date: May 2016 class coverage_goalst { public: - void get_coverage(const std::string &coverage, - message_handlert &message_handler); + static coverage_goalst get_coverage_goals(const std::string &coverage, + message_handlert &message_handler); void set_goals(source_locationt goal); bool is_existing_goal(source_locationt source_location); From 6bf5c14f0f02a5626305a5fcb192df61fbc8d7f5 Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Thu, 8 Sep 2016 15:19:19 +0100 Subject: [PATCH 081/699] use json file suggested at github issue #187 --- src/goto-instrument/cover.cpp | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index 974e3aab9ff..d88482de82d 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -8,6 +8,8 @@ Date: May 2016 \*******************************************************************/ +#include + #include #include #include @@ -135,24 +137,33 @@ coverage_goalst coverage_goalst::get_coverage_goals(const std::string &coverage, exit(0); } - irep_idt line_number; + irep_idt file, function, line; for(jsont::arrayt::const_iterator it=json.array.begin(); it!=json.array.end(); it++) { - //get the goals array - if ((*it)["goals"].is_array()) + + //get the file of each existing goal + file=(*it)["file"].value; + source_location.set_file(file); + + //get the function of each existing goal + function=(*it)["function"].value; + source_location.set_function(function); + + //get the lines array + if ((*it)["lines"].is_array()) { for(jsont::arrayt::const_iterator - itg=(*it)["goals"].array.begin(); - itg!=(*it)["goals"].array.end(); + itg=(*it)["lines"].array.begin(); + itg!=(*it)["lines"].array.end(); itg++) { //get the line of each existing goal - line_number=(*itg)["sourceLocation"]["line"].value; - source_location.set_line(line_number); - goals.set_goals(source_location); + line=(*itg)["number"].value; + source_location.set_line(line); + goals.set_goals(source_location); } } } @@ -193,7 +204,9 @@ bool coverage_goalst::is_existing_goal(source_locationt source_location) std::vector::iterator it = existing_goals.begin(); while (it!=existing_goals.end()) { - if (!source_location.get_line().compare(it->get_line())) + if (!source_location.get_file().compare(it->get_file()) && + !source_location.get_function().compare(it->get_function()) && + !source_location.get_line().compare(it->get_line())) break; ++it; } From 51ecf5166e6d5d7855705e19135dc4a989f862c8 Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Wed, 14 Sep 2016 15:16:27 +0100 Subject: [PATCH 082/699] add consider_goals method --- src/goto-instrument/cover.cpp | 46 ++++++++++++++++++++++++++++++++--- src/goto-instrument/cover.h | 3 +++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index d88482de82d..601ba787b6a 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -1590,9 +1590,47 @@ void instrument_cover_goals( f_it->first=="__CPROVER_initialize") continue; - //empty set of existing goals - coverage_goalst goals; - instrument_cover_goals(symbol_table, f_it->second.body, - criterion, goals); + //exclude trivial coverage goals of a goto program + if (consider_goals(f_it->second.body)) + { + //empty set of existing goals + coverage_goalst goals; + instrument_cover_goals(symbol_table, f_it->second.body, + criterion, goals); + } } } +/*******************************************************************\ + +Function: consider_goals + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool consider_goals( + const goto_programt &goto_program) +{ + bool result; + unsigned long count_assignments=0, count_goto=0, count_decl=0; + + forall_goto_program_instructions(i_it, goto_program) + { + if(i_it->is_goto()) + ++count_goto; + else if (i_it->is_assign()) + ++count_assignments; + else if (i_it->is_decl()) + ++count_decl; + } + + //this might be a get or set method (pattern) + result = !((count_decl==0) && (count_goto<=1) && + (count_assignments>0 && count_assignments<5)); + + return result; +} diff --git a/src/goto-instrument/cover.h b/src/goto-instrument/cover.h index 6dca58da366..37e77d66494 100644 --- a/src/goto-instrument/cover.h +++ b/src/goto-instrument/cover.h @@ -30,6 +30,9 @@ enum class coverage_criteriont LOCATION, BRANCH, DECISION, CONDITION, PATH, MCDC, ASSERTION, COVER }; +bool consider_goals( + const goto_programt &goto_program); + void instrument_cover_goals( const symbol_tablet &symbol_table, goto_programt &goto_program, From 2440baf68150ec8e420985f079626d7c6e18db13 Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Wed, 14 Sep 2016 16:38:49 +0100 Subject: [PATCH 083/699] add the --no-trivial-tests option to CBMC Signed-off-by: Lucas Cordeiro --- src/goto-instrument/cover.cpp | 74 +++++++++++++++++++++++++++++------ src/goto-instrument/cover.h | 7 +++- 2 files changed, 69 insertions(+), 12 deletions(-) diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index 601ba787b6a..b6de039b826 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -8,8 +8,6 @@ Date: May 2016 \*******************************************************************/ -#include - #include #include #include @@ -102,6 +100,23 @@ class basic_blockst /*******************************************************************\ +Function: coverage_goalst::coverage_goalst + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +coverage_goalst::coverage_goalst() +{ + no_trivial_tests=false; +} + +/*******************************************************************\ + Function: coverage_goalst::get_coverage Inputs: @@ -118,6 +133,7 @@ coverage_goalst coverage_goalst::get_coverage_goals(const std::string &coverage, jsont json; coverage_goalst goals; source_locationt source_location; + goals.set_no_trivial_tests(false); //check coverage file if(parse_json(coverage, message_handler, json)) @@ -216,6 +232,39 @@ bool coverage_goalst::is_existing_goal(source_locationt source_location) return false; } +/*******************************************************************\ + +Function: coverage_goalst::set_no_trivial_tests + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void coverage_goalst::set_no_trivial_tests(const bool trivial) +{ + no_trivial_tests=trivial; +} + +/*******************************************************************\ + +Function: coverage_goalst::get_no_trivial_tests + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +const bool coverage_goalst::get_no_trivial_tests() +{ + return no_trivial_tests; +} /*******************************************************************\ @@ -1590,16 +1639,13 @@ void instrument_cover_goals( f_it->first=="__CPROVER_initialize") continue; - //exclude trivial coverage goals of a goto program - if (consider_goals(f_it->second.body)) - { - //empty set of existing goals - coverage_goalst goals; - instrument_cover_goals(symbol_table, f_it->second.body, - criterion, goals); - } + //empty set of existing goals + coverage_goalst goals; + instrument_cover_goals(symbol_table, f_it->second.body, + criterion, goals); } } + /*******************************************************************\ Function: consider_goals @@ -1613,8 +1659,13 @@ Function: consider_goals \*******************************************************************/ bool consider_goals( - const goto_programt &goto_program) + const goto_programt &goto_program, + coverage_goalst &goals) { + //check whether we should eliminate trivial goals + if (!goals.get_no_trivial_tests()) + return true; + bool result; unsigned long count_assignments=0, count_goto=0, count_decl=0; @@ -1634,3 +1685,4 @@ bool consider_goals( return result; } + diff --git a/src/goto-instrument/cover.h b/src/goto-instrument/cover.h index 37e77d66494..07ced79178c 100644 --- a/src/goto-instrument/cover.h +++ b/src/goto-instrument/cover.h @@ -16,13 +16,17 @@ Date: May 2016 class coverage_goalst { public: + coverage_goalst(); static coverage_goalst get_coverage_goals(const std::string &coverage, message_handlert &message_handler); void set_goals(source_locationt goal); bool is_existing_goal(source_locationt source_location); + void set_no_trivial_tests(const bool trivial); + const bool get_no_trivial_tests(); private: std::vector existing_goals; + bool no_trivial_tests; }; enum class coverage_criteriont @@ -31,7 +35,8 @@ enum class coverage_criteriont PATH, MCDC, ASSERTION, COVER }; bool consider_goals( - const goto_programt &goto_program); + const goto_programt &goto_program, + coverage_goalst &goals); void instrument_cover_goals( const symbol_tablet &symbol_table, From 7e71a71c87c5514f6a3759691b62584093f2fc80 Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Thu, 15 Sep 2016 16:49:13 +0100 Subject: [PATCH 084/699] do not produce test goals for constructor and destructor methods --- src/cbmc/Makefile | 3 +- src/goto-instrument/cover.cpp | 75 ++++++++++++++++++----------------- 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/src/cbmc/Makefile b/src/cbmc/Makefile index 804030ea69a..8bf055fe3b2 100644 --- a/src/cbmc/Makefile +++ b/src/cbmc/Makefile @@ -27,7 +27,8 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \ ../xmllang/xmllang$(LIBEXT) \ ../assembler/assembler$(LIBEXT) \ ../solvers/solvers$(LIBEXT) \ - ../util/util$(LIBEXT) + ../util/util$(LIBEXT) \ + ../json/json$(LIBEXT) INCLUDES= -I .. diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index b6de039b826..4623eb782bf 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -135,22 +135,23 @@ coverage_goalst coverage_goalst::get_coverage_goals(const std::string &coverage, source_locationt source_location; goals.set_no_trivial_tests(false); - //check coverage file + // check coverage file if(parse_json(coverage, message_handler, json)) { messaget message(message_handler); message.error() << coverage << " file is not a valid json file" << messaget::eom; - exit(0); + exit(6); } - //make sure that we have an array of elements + // make sure that we have an array of elements if(!json.is_array()) { messaget message(message_handler); - message.error() << "expecting an array in the " << coverage << " file, but got " + message.error() << "expecting an array in the " << coverage + << " file, but got " << json << messaget::eom; - exit(0); + exit(6); } irep_idt file, function, line; @@ -159,29 +160,28 @@ coverage_goalst coverage_goalst::get_coverage_goals(const std::string &coverage, it!=json.array.end(); it++) { - - //get the file of each existing goal + // get the file of each existing goal file=(*it)["file"].value; source_location.set_file(file); - //get the function of each existing goal + // get the function of each existing goal function=(*it)["function"].value; source_location.set_function(function); - //get the lines array - if ((*it)["lines"].is_array()) - { - for(jsont::arrayt::const_iterator - itg=(*it)["lines"].array.begin(); - itg!=(*it)["lines"].array.end(); - itg++) - { - //get the line of each existing goal + // get the lines array + if((*it)["lines"].is_array()) + { + for(jsont::arrayt::const_iterator + itg=(*it)["lines"].array.begin(); + itg!=(*it)["lines"].array.end(); + itg++) + { + // get the line of each existing goal line=(*itg)["number"].value; source_location.set_line(line); goals.set_goals(source_location); - } - } + } + } } return goals; } @@ -218,12 +218,12 @@ Function: coverage_goalst::is_existing_goal bool coverage_goalst::is_existing_goal(source_locationt source_location) { std::vector::iterator it = existing_goals.begin(); - while (it!=existing_goals.end()) + while(it!=existing_goals.end()) { - if (!source_location.get_file().compare(it->get_file()) && - !source_location.get_function().compare(it->get_function()) && - !source_location.get_line().compare(it->get_line())) - break; + if(!source_location.get_file().compare(it->get_file()) && + !source_location.get_function().compare(it->get_function()) && + !source_location.get_line().compare(it->get_line())) + break; ++it; } if(it == existing_goals.end()) @@ -1347,9 +1347,9 @@ void instrument_cover_goals( source_locationt source_location= basic_blocks.source_location_map[block_nr]; - //check whether the current goal already exists + // check whether the current goal already exists if(goals.is_existing_goal(source_location) && - !source_location.get_file().empty() && + !source_location.get_file().empty() && source_location.get_file()[0]!='<') { std::string comment="block "+b; @@ -1639,10 +1639,10 @@ void instrument_cover_goals( f_it->first=="__CPROVER_initialize") continue; - //empty set of existing goals + // empty set of existing goals coverage_goalst goals; instrument_cover_goals(symbol_table, f_it->second.body, - criterion, goals); + criterion, goals); } } @@ -1662,8 +1662,8 @@ bool consider_goals( const goto_programt &goto_program, coverage_goalst &goals) { - //check whether we should eliminate trivial goals - if (!goals.get_no_trivial_tests()) + // check whether we should eliminate trivial goals + if(!goals.get_no_trivial_tests()) return true; bool result; @@ -1672,16 +1672,19 @@ bool consider_goals( forall_goto_program_instructions(i_it, goto_program) { if(i_it->is_goto()) - ++count_goto; - else if (i_it->is_assign()) + ++count_goto; + else if(i_it->is_assign()) ++count_assignments; - else if (i_it->is_decl()) + else if(i_it->is_decl()) ++count_decl; } - //this might be a get or set method (pattern) - result = !((count_decl==0) && (count_goto<=1) && - (count_assignments>0 && count_assignments<5)); + // check whether this is a constructor/destructor or a get/set (pattern) + if(!count_goto && !count_assignments && !count_decl) + result=false; + else + result = !((count_decl==0) && (count_goto<=1) && + (count_assignments>0 && count_assignments<5)); return result; } From 6cc36c15604ae1f3b82542fa8e3ce10a07f9ca9e Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Tue, 14 Mar 2017 16:30:43 +0000 Subject: [PATCH 085/699] added CPROVER_initialize Signed-off-by: Lucas Cordeiro --- src/goto-instrument/cover.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index 4623eb782bf..2385c4204f3 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -15,6 +15,7 @@ Date: May 2016 #include #include #include +#include #include @@ -171,13 +172,10 @@ coverage_goalst coverage_goalst::get_coverage_goals(const std::string &coverage, // get the lines array if((*it)["lines"].is_array()) { - for(jsont::arrayt::const_iterator - itg=(*it)["lines"].array.begin(); - itg!=(*it)["lines"].array.end(); - itg++) + for(const jsont & entry : (*it)["lines"].array) { // get the line of each existing goal - line=(*itg)["number"].value; + line=entry["number"].value; source_location.set_line(line); goals.set_goals(source_location); } @@ -1605,7 +1603,7 @@ void instrument_cover_goals( Forall_goto_functions(f_it, goto_functions) { if(f_it->first==ID__start || - f_it->first=="__CPROVER_initialize") + f_it->first==CPROVER_PREFIX "initialize") continue; instrument_cover_goals( From 2cc423e5f4e8ef515b5aae354185760e125473af Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Wed, 15 Mar 2017 10:51:36 +0000 Subject: [PATCH 086/699] added json to cegis makefile Signed-off-by: Lucas Cordeiro --- src/cegis/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cegis/Makefile b/src/cegis/Makefile index 27a6880a651..a126776bd03 100644 --- a/src/cegis/Makefile +++ b/src/cegis/Makefile @@ -115,7 +115,8 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \ ../cbmc/show_vcc$(OBJEXT) \ ../cbmc/cbmc_dimacs$(OBJEXT) ../cbmc/all_properties$(OBJEXT) \ ../cbmc/fault_localization$(OBJEXT) \ - ../cbmc/symex_coverage$(OBJEXT) + ../cbmc/symex_coverage$(OBJEXT) \ + ../json/json$(LIBEXT) INCLUDES= -I .. From 2f06442f9e1c481d87ad064153603333f7930fbb Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 23 Feb 2017 16:50:10 +0000 Subject: [PATCH 087/699] Add json->irep deserialization routine --- src/util/json_irep.cpp | 40 +++++++++++++++++++++++++++++++++++++++- src/util/json_irep.h | 1 + 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/util/json_irep.cpp b/src/util/json_irep.cpp index 7a3d1a8f2bc..403247c1d04 100644 --- a/src/util/json_irep.cpp +++ b/src/util/json_irep.cpp @@ -10,12 +10,14 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com #include "json.h" #include "json_irep.h" +#include + /*******************************************************************\ Function: json_irept::json_irept Inputs: - include_comments - when generating the JSON, should the comments + include_comments - when writing JSON, should the comments sub tree be included. Outputs: @@ -131,3 +133,39 @@ void json_irept::convert_named_sub_tree( } } +/*******************************************************************\ + +Function: json_irept::convert_from_json + + Inputs: input - json object to convert + + Outputs: result - irep equivalent of input + + Purpose: Deserialize a JSON irep representation. + +\*******************************************************************/ + +void json_irept::convert_from_json(const jsont &in, irept &out) const +{ + std::vector have_keys; + for(const auto &keyval : in.object) + have_keys.push_back(keyval.first); + std::sort(have_keys.begin(), have_keys.end()); + if(have_keys!=std::vector{"comment", "id", "namedSub", "sub"}) + throw "irep JSON representation is missing one of needed keys: " + "'id', 'sub', 'namedSub', 'comment'"; + + out.id(in["id"].value); + + for(const auto &sub : in["sub"].array) + { + out.get_sub().push_back(irept()); + convert_from_json(sub, out.get_sub().back()); + } + + for(const auto &named_sub : in["namedSub"].object) + convert_from_json(named_sub.second, out.get_named_sub()[named_sub.first]); + + for(const auto &comment : in["comment"].object) + convert_from_json(comment.second, out.get_comments()[comment.first]); +} diff --git a/src/util/json_irep.h b/src/util/json_irep.h index 749917cb34b..20a364d31e9 100644 --- a/src/util/json_irep.h +++ b/src/util/json_irep.h @@ -18,6 +18,7 @@ class json_irept public: explicit json_irept(bool include_comments); void convert_from_irep(const irept &irep, jsont &json) const; + void convert_from_json(const jsont &, irept &) const; private: void convert_sub_tree( From 4cb8705b2b23513c067c7ff075e511b335fff3ca Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Fri, 3 Mar 2017 10:46:24 +0000 Subject: [PATCH 088/699] set EXIT to 10 to all failing string-solver test cases set EXIT to 10 in the test description of each string-solver test case that is supposed to fail --- regression/strings/RegexMatches02/test.desc | 2 +- regression/strings/RegexSubstitution02/test.desc | 2 +- regression/strings/StaticCharMethods02/test.desc | 2 +- regression/strings/StaticCharMethods03/test.desc | 2 +- regression/strings/StaticCharMethods04/test.desc | 2 +- regression/strings/StaticCharMethods05/test.desc | 2 +- regression/strings/StringBuilderAppend02/test.desc | 2 +- regression/strings/StringBuilderCapLen02/test.desc | 2 +- regression/strings/StringBuilderCapLen03/test.desc | 2 +- regression/strings/StringBuilderCapLen04/test.desc | 2 +- regression/strings/StringBuilderChars02/test.desc | 2 +- regression/strings/StringBuilderChars03/test.desc | 2 +- regression/strings/StringBuilderChars04/test.desc | 2 +- regression/strings/StringBuilderChars05/test.desc | 2 +- regression/strings/StringBuilderChars06/test.desc | 2 +- regression/strings/StringBuilderConstructors02/test.desc | 2 +- regression/strings/StringBuilderInsertDelete02/test.desc | 2 +- regression/strings/StringBuilderInsertDelete03/test.desc | 2 +- regression/strings/StringCompare02/test.desc | 2 +- regression/strings/StringCompare03/test.desc | 2 +- regression/strings/StringCompare04/test.desc | 2 +- regression/strings/StringCompare05/test.desc | 2 +- regression/strings/StringConcatenation02/test.desc | 2 +- regression/strings/StringConcatenation03/test.desc | 2 +- regression/strings/StringConcatenation04/test.desc | 2 +- regression/strings/StringConstructors02/test.desc | 2 +- regression/strings/StringConstructors03/test.desc | 2 +- regression/strings/StringConstructors04/test.desc | 2 +- regression/strings/StringConstructors05/test.desc | 2 +- regression/strings/StringIndexMethods02/test.desc | 2 +- regression/strings/StringIndexMethods03/test.desc | 2 +- regression/strings/StringIndexMethods04/test.desc | 2 +- regression/strings/StringIndexMethods05/test.desc | 2 +- regression/strings/StringMiscellaneous02/test.desc | 2 +- regression/strings/StringMiscellaneous03/test.desc | 2 +- regression/strings/StringStartEnd02/test.desc | 2 +- regression/strings/StringStartEnd03/test.desc | 2 +- regression/strings/StringValueOf02/test.desc | 2 +- regression/strings/StringValueOf03/test.desc | 2 +- regression/strings/StringValueOf04/test.desc | 2 +- regression/strings/StringValueOf05/test.desc | 2 +- regression/strings/StringValueOf06/test.desc | 2 +- regression/strings/StringValueOf07/test.desc | 2 +- regression/strings/StringValueOf08/test.desc | 2 +- regression/strings/StringValueOf09/test.desc | 2 +- regression/strings/StringValueOf10/test.desc | 2 +- regression/strings/SubString02/test.desc | 2 +- regression/strings/SubString03/test.desc | 2 +- regression/strings/TokenTest02/test.desc | 2 +- regression/strings/Validate02/test.desc | 2 +- 50 files changed, 50 insertions(+), 50 deletions(-) diff --git a/regression/strings/RegexMatches02/test.desc b/regression/strings/RegexMatches02/test.desc index 92d72ae941e..86353d9a54c 100644 --- a/regression/strings/RegexMatches02/test.desc +++ b/regression/strings/RegexMatches02/test.desc @@ -1,7 +1,7 @@ FUTURE RegexMatches02.class --string-refine --unwind 100 -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/RegexSubstitution02/test.desc b/regression/strings/RegexSubstitution02/test.desc index eb2c03599a1..0645c3ac9b8 100644 --- a/regression/strings/RegexSubstitution02/test.desc +++ b/regression/strings/RegexSubstitution02/test.desc @@ -1,7 +1,7 @@ FUTURE RegexSubstitution02.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StaticCharMethods02/test.desc b/regression/strings/StaticCharMethods02/test.desc index 496814588a7..00aaaba8964 100644 --- a/regression/strings/StaticCharMethods02/test.desc +++ b/regression/strings/StaticCharMethods02/test.desc @@ -1,7 +1,7 @@ FUTURE StaticCharMethods02.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StaticCharMethods03/test.desc b/regression/strings/StaticCharMethods03/test.desc index d48bf57dbba..6f3d3bc5607 100644 --- a/regression/strings/StaticCharMethods03/test.desc +++ b/regression/strings/StaticCharMethods03/test.desc @@ -1,7 +1,7 @@ FUTURE StaticCharMethods03.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StaticCharMethods04/test.desc b/regression/strings/StaticCharMethods04/test.desc index 93eebbae1da..0c9484ef337 100644 --- a/regression/strings/StaticCharMethods04/test.desc +++ b/regression/strings/StaticCharMethods04/test.desc @@ -1,7 +1,7 @@ FUTURE StaticCharMethods04.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StaticCharMethods05/test.desc b/regression/strings/StaticCharMethods05/test.desc index e009650a853..5b4a6b4b622 100644 --- a/regression/strings/StaticCharMethods05/test.desc +++ b/regression/strings/StaticCharMethods05/test.desc @@ -1,7 +1,7 @@ FUTURE StaticCharMethods05.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringBuilderAppend02/test.desc b/regression/strings/StringBuilderAppend02/test.desc index 4ff9da595b5..1336c45c3d2 100644 --- a/regression/strings/StringBuilderAppend02/test.desc +++ b/regression/strings/StringBuilderAppend02/test.desc @@ -1,7 +1,7 @@ FUTURE StringBuilderAppend02.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringBuilderCapLen02/test.desc b/regression/strings/StringBuilderCapLen02/test.desc index cf2a98acf6d..72a0bbd72c2 100644 --- a/regression/strings/StringBuilderCapLen02/test.desc +++ b/regression/strings/StringBuilderCapLen02/test.desc @@ -1,7 +1,7 @@ FUTURE StringBuilderCapLen02.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringBuilderCapLen03/test.desc b/regression/strings/StringBuilderCapLen03/test.desc index 7095d79fe5f..474bdc661ab 100644 --- a/regression/strings/StringBuilderCapLen03/test.desc +++ b/regression/strings/StringBuilderCapLen03/test.desc @@ -1,7 +1,7 @@ FUTURE StringBuilderCapLen03.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringBuilderCapLen04/test.desc b/regression/strings/StringBuilderCapLen04/test.desc index ce51066e789..fa342b79518 100644 --- a/regression/strings/StringBuilderCapLen04/test.desc +++ b/regression/strings/StringBuilderCapLen04/test.desc @@ -1,7 +1,7 @@ FUTURE StringBuilderCapLen04.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringBuilderChars02/test.desc b/regression/strings/StringBuilderChars02/test.desc index 3a6bde6ef78..50e49d474bc 100644 --- a/regression/strings/StringBuilderChars02/test.desc +++ b/regression/strings/StringBuilderChars02/test.desc @@ -1,7 +1,7 @@ FUTURE StringBuilderChars02.class --string-refine --unwind 100 -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringBuilderChars03/test.desc b/regression/strings/StringBuilderChars03/test.desc index 12f20189434..23dda39df4e 100644 --- a/regression/strings/StringBuilderChars03/test.desc +++ b/regression/strings/StringBuilderChars03/test.desc @@ -1,7 +1,7 @@ FUTURE StringBuilderChars03.class --string-refine --unwind 100 -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringBuilderChars04/test.desc b/regression/strings/StringBuilderChars04/test.desc index a2658cf2fe4..a68edd89395 100644 --- a/regression/strings/StringBuilderChars04/test.desc +++ b/regression/strings/StringBuilderChars04/test.desc @@ -1,7 +1,7 @@ FUTURE StringBuilderChars04.class --string-refine --unwind 100 -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringBuilderChars05/test.desc b/regression/strings/StringBuilderChars05/test.desc index 2bcbdbab934..eeac328e02b 100644 --- a/regression/strings/StringBuilderChars05/test.desc +++ b/regression/strings/StringBuilderChars05/test.desc @@ -1,7 +1,7 @@ FUTURE StringBuilderChars05.class --string-refine --unwind 100 -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringBuilderChars06/test.desc b/regression/strings/StringBuilderChars06/test.desc index 4a711edf496..a3dc3712a5a 100644 --- a/regression/strings/StringBuilderChars06/test.desc +++ b/regression/strings/StringBuilderChars06/test.desc @@ -1,7 +1,7 @@ FUTURE StringBuilderChars06.class --string-refine --unwind 100 -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringBuilderConstructors02/test.desc b/regression/strings/StringBuilderConstructors02/test.desc index 8cbad8cfe16..5e951bc8079 100644 --- a/regression/strings/StringBuilderConstructors02/test.desc +++ b/regression/strings/StringBuilderConstructors02/test.desc @@ -1,7 +1,7 @@ KNOWNBUG StringBuilderConstructors02.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringBuilderInsertDelete02/test.desc b/regression/strings/StringBuilderInsertDelete02/test.desc index f78bf3f983a..ae4d0ca5b81 100644 --- a/regression/strings/StringBuilderInsertDelete02/test.desc +++ b/regression/strings/StringBuilderInsertDelete02/test.desc @@ -1,7 +1,7 @@ FUTURE StringBuilderInsertDelete02.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringBuilderInsertDelete03/test.desc b/regression/strings/StringBuilderInsertDelete03/test.desc index b3882f41f7e..3dfa92f0338 100644 --- a/regression/strings/StringBuilderInsertDelete03/test.desc +++ b/regression/strings/StringBuilderInsertDelete03/test.desc @@ -1,7 +1,7 @@ FUTURE StringBuilderInsertDelete03.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringCompare02/test.desc b/regression/strings/StringCompare02/test.desc index abc986be65d..eb52d1f1a58 100644 --- a/regression/strings/StringCompare02/test.desc +++ b/regression/strings/StringCompare02/test.desc @@ -1,7 +1,7 @@ FUTURE StringCompare02.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringCompare03/test.desc b/regression/strings/StringCompare03/test.desc index fa518907143..bd0f3177acf 100644 --- a/regression/strings/StringCompare03/test.desc +++ b/regression/strings/StringCompare03/test.desc @@ -1,7 +1,7 @@ FUTURE StringCompare03.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringCompare04/test.desc b/regression/strings/StringCompare04/test.desc index f1b2a9790cc..88ecddbfcf6 100644 --- a/regression/strings/StringCompare04/test.desc +++ b/regression/strings/StringCompare04/test.desc @@ -1,7 +1,7 @@ FUTURE StringCompare04.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringCompare05/test.desc b/regression/strings/StringCompare05/test.desc index 159809fac0f..1358a05a36b 100644 --- a/regression/strings/StringCompare05/test.desc +++ b/regression/strings/StringCompare05/test.desc @@ -1,7 +1,7 @@ FUTURE StringCompare05.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringConcatenation02/test.desc b/regression/strings/StringConcatenation02/test.desc index 937caa3295e..0e1faf53d5e 100644 --- a/regression/strings/StringConcatenation02/test.desc +++ b/regression/strings/StringConcatenation02/test.desc @@ -1,7 +1,7 @@ KNOWNBUG StringConcatenation02.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringConcatenation03/test.desc b/regression/strings/StringConcatenation03/test.desc index 26ccc899a87..3c01a4ee0a9 100644 --- a/regression/strings/StringConcatenation03/test.desc +++ b/regression/strings/StringConcatenation03/test.desc @@ -1,7 +1,7 @@ FUTURE StringConcatenation03.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringConcatenation04/test.desc b/regression/strings/StringConcatenation04/test.desc index ea980c45d54..3dbecf065ba 100644 --- a/regression/strings/StringConcatenation04/test.desc +++ b/regression/strings/StringConcatenation04/test.desc @@ -1,7 +1,7 @@ FUTURE StringConcatenation04.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringConstructors02/test.desc b/regression/strings/StringConstructors02/test.desc index c2a30b3534c..e3904d1d557 100644 --- a/regression/strings/StringConstructors02/test.desc +++ b/regression/strings/StringConstructors02/test.desc @@ -1,7 +1,7 @@ FUTURE StringConstructors02.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringConstructors03/test.desc b/regression/strings/StringConstructors03/test.desc index 5419e5ae48e..0caf75f41ea 100644 --- a/regression/strings/StringConstructors03/test.desc +++ b/regression/strings/StringConstructors03/test.desc @@ -1,7 +1,7 @@ FUTURE StringConstructors03.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringConstructors04/test.desc b/regression/strings/StringConstructors04/test.desc index 21394f70327..75364dcde22 100644 --- a/regression/strings/StringConstructors04/test.desc +++ b/regression/strings/StringConstructors04/test.desc @@ -1,7 +1,7 @@ FUTURE StringConstructors04.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringConstructors05/test.desc b/regression/strings/StringConstructors05/test.desc index 9804850d77e..e74dfc73f6c 100644 --- a/regression/strings/StringConstructors05/test.desc +++ b/regression/strings/StringConstructors05/test.desc @@ -1,7 +1,7 @@ FUTURE StringConstructors05.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringIndexMethods02/test.desc b/regression/strings/StringIndexMethods02/test.desc index cad6c487fae..28df14f0145 100644 --- a/regression/strings/StringIndexMethods02/test.desc +++ b/regression/strings/StringIndexMethods02/test.desc @@ -1,7 +1,7 @@ FUTURE StringIndexMethods02.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringIndexMethods03/test.desc b/regression/strings/StringIndexMethods03/test.desc index 3dff0b27714..02f9934726b 100644 --- a/regression/strings/StringIndexMethods03/test.desc +++ b/regression/strings/StringIndexMethods03/test.desc @@ -1,7 +1,7 @@ FUTURE StringIndexMethods03.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringIndexMethods04/test.desc b/regression/strings/StringIndexMethods04/test.desc index 758f22d2bf4..cb94fecb6a6 100644 --- a/regression/strings/StringIndexMethods04/test.desc +++ b/regression/strings/StringIndexMethods04/test.desc @@ -1,7 +1,7 @@ FUTURE StringIndexMethods04.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringIndexMethods05/test.desc b/regression/strings/StringIndexMethods05/test.desc index d415ef1381e..cb43b009246 100644 --- a/regression/strings/StringIndexMethods05/test.desc +++ b/regression/strings/StringIndexMethods05/test.desc @@ -1,7 +1,7 @@ FUTURE StringIndexMethods05.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringMiscellaneous02/test.desc b/regression/strings/StringMiscellaneous02/test.desc index 53c46cf1a7f..8f1a1d9475f 100644 --- a/regression/strings/StringMiscellaneous02/test.desc +++ b/regression/strings/StringMiscellaneous02/test.desc @@ -1,7 +1,7 @@ FUTURE StringMiscellaneous02.class --string-refine --unwind 30 -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringMiscellaneous03/test.desc b/regression/strings/StringMiscellaneous03/test.desc index f255272ed5b..341867d536f 100644 --- a/regression/strings/StringMiscellaneous03/test.desc +++ b/regression/strings/StringMiscellaneous03/test.desc @@ -1,7 +1,7 @@ FUTURE StringMiscellaneous03.class --string-refine --unwind 30 -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringStartEnd02/test.desc b/regression/strings/StringStartEnd02/test.desc index 16f696efa01..8e623622f72 100644 --- a/regression/strings/StringStartEnd02/test.desc +++ b/regression/strings/StringStartEnd02/test.desc @@ -1,7 +1,7 @@ KNOWNBUG StringStartEnd02.class --string-refine --unwind 30 -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringStartEnd03/test.desc b/regression/strings/StringStartEnd03/test.desc index e6d8c460709..2903ec98e3e 100644 --- a/regression/strings/StringStartEnd03/test.desc +++ b/regression/strings/StringStartEnd03/test.desc @@ -1,7 +1,7 @@ KNOWNBUG StringStartEnd03.class --string-refine --unwind 15 -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringValueOf02/test.desc b/regression/strings/StringValueOf02/test.desc index 00835385bc8..a10b398bf41 100644 --- a/regression/strings/StringValueOf02/test.desc +++ b/regression/strings/StringValueOf02/test.desc @@ -1,7 +1,7 @@ FUTURE StringValueOf02.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringValueOf03/test.desc b/regression/strings/StringValueOf03/test.desc index 19921a8e98f..4ed709a2404 100644 --- a/regression/strings/StringValueOf03/test.desc +++ b/regression/strings/StringValueOf03/test.desc @@ -1,7 +1,7 @@ FUTURE StringValueOf03.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringValueOf04/test.desc b/regression/strings/StringValueOf04/test.desc index 1312d27676d..0d8442e9de1 100644 --- a/regression/strings/StringValueOf04/test.desc +++ b/regression/strings/StringValueOf04/test.desc @@ -1,7 +1,7 @@ KNOWNBUG StringValueOf04.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringValueOf05/test.desc b/regression/strings/StringValueOf05/test.desc index ccb5b3dc440..f77cdef0b8e 100644 --- a/regression/strings/StringValueOf05/test.desc +++ b/regression/strings/StringValueOf05/test.desc @@ -1,7 +1,7 @@ KNOWNBUG StringValueOf05.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringValueOf06/test.desc b/regression/strings/StringValueOf06/test.desc index c78afa98f2f..56551c4a14b 100644 --- a/regression/strings/StringValueOf06/test.desc +++ b/regression/strings/StringValueOf06/test.desc @@ -1,7 +1,7 @@ KNOWNBUG StringValueOf06.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringValueOf07/test.desc b/regression/strings/StringValueOf07/test.desc index 7b19c4ff67b..6dde9de229d 100644 --- a/regression/strings/StringValueOf07/test.desc +++ b/regression/strings/StringValueOf07/test.desc @@ -1,7 +1,7 @@ KNOWNBUG StringValueOf07.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringValueOf08/test.desc b/regression/strings/StringValueOf08/test.desc index a7d90b1b9ef..21d64075aaf 100644 --- a/regression/strings/StringValueOf08/test.desc +++ b/regression/strings/StringValueOf08/test.desc @@ -1,7 +1,7 @@ FUTURE StringValueOf08.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringValueOf09/test.desc b/regression/strings/StringValueOf09/test.desc index 10f6b102a67..4ff97a7caef 100644 --- a/regression/strings/StringValueOf09/test.desc +++ b/regression/strings/StringValueOf09/test.desc @@ -1,7 +1,7 @@ FUTURE StringValueOf09.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/StringValueOf10/test.desc b/regression/strings/StringValueOf10/test.desc index 5de3d5aade7..10e7f184189 100644 --- a/regression/strings/StringValueOf10/test.desc +++ b/regression/strings/StringValueOf10/test.desc @@ -1,7 +1,7 @@ FUTURE StringValueOf10.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/SubString02/test.desc b/regression/strings/SubString02/test.desc index e7b21cdd678..063ce88f0f2 100644 --- a/regression/strings/SubString02/test.desc +++ b/regression/strings/SubString02/test.desc @@ -1,7 +1,7 @@ KNOWNBUG SubString02.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/SubString03/test.desc b/regression/strings/SubString03/test.desc index 2b8db21a829..f985329ce2d 100644 --- a/regression/strings/SubString03/test.desc +++ b/regression/strings/SubString03/test.desc @@ -1,7 +1,7 @@ KNOWNBUG SubString03.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/TokenTest02/test.desc b/regression/strings/TokenTest02/test.desc index 3bcf7505e25..48e6b0c1ab6 100644 --- a/regression/strings/TokenTest02/test.desc +++ b/regression/strings/TokenTest02/test.desc @@ -1,7 +1,7 @@ FUTURE TokenTest02.class --string-refine --unwind 15 -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- diff --git a/regression/strings/Validate02/test.desc b/regression/strings/Validate02/test.desc index b30016bf880..a5a3a6f1d20 100644 --- a/regression/strings/Validate02/test.desc +++ b/regression/strings/Validate02/test.desc @@ -1,7 +1,7 @@ FUTURE Validate02.class --string-refine -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ -- From bbe06ad691d165f1dfc54b86cac0501ff4e931e6 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 30 Nov 2016 11:00:31 +0000 Subject: [PATCH 089/699] Java checkcast: fix stack when check disabled The checkcast instruction should always return the pointer it checked, even when we're not generating an assert in the case that it failed. --- src/java_bytecode/java_bytecode_convert_method.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index e0ffe460f77..3ce43acff02 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -1116,10 +1116,11 @@ codet java_bytecode_convert_methodt::convert_instructions( c=code_assertt(check); c.add_source_location().set_comment("Dynamic cast check"); c.add_source_location().set_property_class("bad-dynamic-cast"); - results[0]=op[0]; } else c=code_skipt(); + + results[0]=op[0]; } else if(statement=="invokedynamic") { From 4854c9a350a52e0a515a78b6c089ab5bbec682d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Tue, 14 Feb 2017 11:53:11 +0100 Subject: [PATCH 090/699] initial support for miniz --- src/java_bytecode/jar_file.cpp | 92 +++++++++++++--------------------- src/java_bytecode/jar_file.h | 14 ++++-- 2 files changed, 45 insertions(+), 61 deletions(-) diff --git a/src/java_bytecode/jar_file.cpp b/src/java_bytecode/jar_file.cpp index 09c18a9cb4c..d679f21c070 100644 --- a/src/java_bytecode/jar_file.cpp +++ b/src/java_bytecode/jar_file.cpp @@ -6,15 +6,12 @@ Author: Daniel Kroening, kroening@kroening.com \*******************************************************************/ +#include #include #include #include "jar_file.h" -#ifdef HAVE_LIBZIP -#include -#endif - /*******************************************************************\ Function: jar_filet::open @@ -29,33 +26,32 @@ Function: jar_filet::open void jar_filet::open(const std::string &filename) { - #ifdef HAVE_LIBZIP - if(zip!=nullptr) - // NOLINTNEXTLINE(readability/identifiers) - zip_close(static_cast(zip)); - - int zip_error; - zip=zip_open(filename.c_str(), 0, &zip_error); + if(!mz_ok) + { + memset(&zip, 0, sizeof(zip)); + mz_bool mz_open=mz_zip_reader_init_file(&zip, filename.c_str(), 0); + mz_ok=mz_open==MZ_TRUE; + } - if(zip!=nullptr) + if(mz_ok) { std::size_t number_of_files= - // NOLINTNEXTLINE(readability/identifiers) - zip_get_num_entries(static_cast(zip), 0); + mz_zip_reader_get_num_files(&zip); index.reserve(number_of_files); for(std::size_t i=0; i(zip), i, 0); + mz_uint filename_length=mz_zip_reader_get_filename(&zip, i, nullptr, 0); + char *filename_char=new char[filename_length+1]; + mz_uint filename_len= + mz_zip_reader_get_filename(&zip, i, filename_char, filename_length); + assert(filename_length==filename_len); + std::string file_name(filename_char); + delete[] filename_char; index.push_back(file_name); } } - #else - zip=nullptr; - #endif } /*******************************************************************\ @@ -72,11 +68,11 @@ Function: jar_filet::~jar_filet jar_filet::~jar_filet() { - #ifdef HAVE_LIBZIP - if(zip!=nullptr) - // NOLINTNEXTLINE(readability/identifiers) - zip_close(static_cast(zip)); - #endif + if(mz_ok) + { + mz_zip_reader_end(&zip); + mz_ok=false; + } } /*******************************************************************\ @@ -91,47 +87,29 @@ Function: jar_filet::get_entry \*******************************************************************/ -#define ZIP_READ_SIZE 10000 - std::string jar_filet::get_entry(std::size_t i) { - if(zip==nullptr) + if(!mz_ok) return std::string(""); assert(i(zip_e); - - // NOLINTNEXTLINE(readability/identifiers) - struct zip_file *zip_file=zip_fopen_index(zip_p, i, 0); - - if(zip_file==NULL) - { - zip_close(zip_p); - zip=nullptr; - return std::string(""); // error - } - + mz_zip_archive_file_stat file_stat; + memset(&file_stat, 0, sizeof(file_stat)); + mz_bool stat_ok=mz_zip_reader_file_stat(&zip, i, &file_stat); + if(stat_ok!=MZ_TRUE) + return std::string(); std::vector buffer; - buffer.resize(ZIP_READ_SIZE); - - while(true) - { - int bytes_read= - zip_fread(zip_file, buffer.data(), ZIP_READ_SIZE); - assert(bytes_read<=ZIP_READ_SIZE); - if(bytes_read<=0) - break; - dest.insert(dest.end(), buffer.begin(), buffer.begin()+bytes_read); - } - - zip_fclose(zip_file); - #endif + size_t bufsize=file_stat.m_uncomp_size; + buffer.resize(bufsize); + mz_bool read_ok= + mz_zip_reader_extract_to_mem(&zip, i, buffer.data(), bufsize, 0); + if(read_ok!=MZ_TRUE) + return std::string(); + + dest.insert(dest.end(), buffer.begin(), buffer.end()); return dest; } diff --git a/src/java_bytecode/jar_file.h b/src/java_bytecode/jar_file.h index a128a2fcc37..6c2229d65be 100644 --- a/src/java_bytecode/jar_file.h +++ b/src/java_bytecode/jar_file.h @@ -9,6 +9,10 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_JAVA_BYTECODE_JAR_FILE_H #define CPROVER_JAVA_BYTECODE_JAR_FILE_H +//#define MINIZ_HEADER_FILE_ONLY +#define _LARGEFILE64_SOURCE 1 +#include "miniz_zip.h" + #include #include #include @@ -16,9 +20,9 @@ Author: Daniel Kroening, kroening@kroening.com class jar_filet { public: - jar_filet():zip(nullptr) { } + jar_filet():mz_ok(false) { } - explicit jar_filet(const std::string &file_name):zip(nullptr) + inline explicit jar_filet(const std::string &file_name) { open(file_name); } @@ -28,7 +32,8 @@ class jar_filet void open(const std::string &); // Test for error; 'true' means we are good. - explicit operator bool() const { return zip!=nullptr; } + inline explicit operator bool() const { return true; // TODO + } typedef std::vector indext; indext index; @@ -39,7 +44,8 @@ class jar_filet manifestt get_manifest(); protected: - void *zip; + mz_zip_archive zip; + bool mz_ok; }; class jar_poolt From 7d2536db699eafdb85c57324b00b85d048269209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Thu, 23 Feb 2017 12:39:16 +0100 Subject: [PATCH 091/699] use amalgamated files from release tarball --- src/java_bytecode/jar_file.h | 3 +- src/miniz/Makefile | 15 + src/miniz/miniz.cpp | 7189 ++++++++++++++++++++++++++++++++++ src/miniz/miniz.h | 1352 +++++++ 4 files changed, 8557 insertions(+), 2 deletions(-) create mode 100644 src/miniz/Makefile create mode 100644 src/miniz/miniz.cpp create mode 100644 src/miniz/miniz.h diff --git a/src/java_bytecode/jar_file.h b/src/java_bytecode/jar_file.h index 6c2229d65be..53f673102bf 100644 --- a/src/java_bytecode/jar_file.h +++ b/src/java_bytecode/jar_file.h @@ -9,9 +9,8 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_JAVA_BYTECODE_JAR_FILE_H #define CPROVER_JAVA_BYTECODE_JAR_FILE_H -//#define MINIZ_HEADER_FILE_ONLY #define _LARGEFILE64_SOURCE 1 -#include "miniz_zip.h" +#include "miniz/miniz.h" #include #include diff --git a/src/miniz/Makefile b/src/miniz/Makefile new file mode 100644 index 00000000000..f2367695802 --- /dev/null +++ b/src/miniz/Makefile @@ -0,0 +1,15 @@ +SRC = miniz.cpp + +INCLUDES= -I .. + +include ../config.inc +include ../common + +CLEANFILES = miniz$(LIBEXT) + +all: miniz$(LIBEXT) + +############################################################################### + +miniz$(LIBEXT): $(OBJ) + $(LINKLIB) diff --git a/src/miniz/miniz.cpp b/src/miniz/miniz.cpp new file mode 100644 index 00000000000..fa5c1903e83 --- /dev/null +++ b/src/miniz/miniz.cpp @@ -0,0 +1,7189 @@ +/************************************************************************** + * + * Copyright 2013-2014 RAD Game Tools and Valve Software + * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + +#include "miniz.h" + +typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1]; +typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1]; +typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1]; + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------- zlib-style API's */ + +mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) +{ + mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); + size_t block_len = buf_len % 5552; + if (!ptr) + return MZ_ADLER32_INIT; + while (buf_len) + { + for (i = 0; i + 7 < block_len; i += 8, ptr += 8) + { + s1 += ptr[0], s2 += s1; + s1 += ptr[1], s2 += s1; + s1 += ptr[2], s2 += s1; + s1 += ptr[3], s2 += s1; + s1 += ptr[4], s2 += s1; + s1 += ptr[5], s2 += s1; + s1 += ptr[6], s2 += s1; + s1 += ptr[7], s2 += s1; + } + for (; i < block_len; ++i) + s1 += *ptr++, s2 += s1; + s1 %= 65521U, s2 %= 65521U; + buf_len -= block_len; + block_len = 5552; + } + return (s2 << 16) + s1; +} + +/* Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ */ +#if 0 + mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) + { + static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; + mz_uint32 crcu32 = (mz_uint32)crc; + if (!ptr) + return MZ_CRC32_INIT; + crcu32 = ~crcu32; + while (buf_len--) + { + mz_uint8 b = *ptr++; + crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; + crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; + } + return ~crcu32; + } +#else +/* Faster, but larger CPU cache footprint. + */ +mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) +{ + static const mz_uint32 s_crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, + 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, + 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, + 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, + 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, + 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, + 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, + 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, + 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, + 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, + 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, + 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, + 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, + 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, + 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, + 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, + 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, + 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, + 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, + 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, + 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, + 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, + 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, + 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, + 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, + 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, + 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, + 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + mz_uint32 crc32 = (mz_uint32)crc ^ 0xFFFFFFFF; + const mz_uint8 *pByte_buf = (const mz_uint8 *)ptr; + + while (buf_len >= 4) + { + crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF]; + crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF]; + crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[2]) & 0xFF]; + crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[3]) & 0xFF]; + pByte_buf += 4; + buf_len -= 4; + } + + while (buf_len) + { + crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF]; + ++pByte_buf; + --buf_len; + } + + return ~crc32; +} +#endif + +void mz_free(void *p) +{ + MZ_FREE(p); +} + +#ifndef MINIZ_NO_ZLIB_APIS + +void *miniz_def_alloc_func(void *opaque, size_t items, size_t size) +{ + (void)opaque, (void)items, (void)size; + return MZ_MALLOC(items * size); +} +void miniz_def_free_func(void *opaque, void *address) +{ + (void)opaque, (void)address; + MZ_FREE(address); +} +void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size) +{ + (void)opaque, (void)address, (void)items, (void)size; + return MZ_REALLOC(address, items * size); +} + +const char *mz_version(void) +{ + return MZ_VERSION; +} + +int mz_deflateInit(mz_streamp pStream, int level) +{ + return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY); +} + +int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy) +{ + tdefl_compressor *pComp; + mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy); + + if (!pStream) + return MZ_STREAM_ERROR; + if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) + return MZ_PARAM_ERROR; + + pStream->data_type = 0; + pStream->adler = MZ_ADLER32_INIT; + pStream->msg = NULL; + pStream->reserved = 0; + pStream->total_in = 0; + pStream->total_out = 0; + if (!pStream->zalloc) + pStream->zalloc = miniz_def_alloc_func; + if (!pStream->zfree) + pStream->zfree = miniz_def_free_func; + + pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor)); + if (!pComp) + return MZ_MEM_ERROR; + + pStream->state = (struct mz_internal_state *)pComp; + + if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) + { + mz_deflateEnd(pStream); + return MZ_PARAM_ERROR; + } + + return MZ_OK; +} + +int mz_deflateReset(mz_streamp pStream) +{ + if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) + return MZ_STREAM_ERROR; + pStream->total_in = pStream->total_out = 0; + tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL, ((tdefl_compressor *)pStream->state)->m_flags); + return MZ_OK; +} + +int mz_deflate(mz_streamp pStream, int flush) +{ + size_t in_bytes, out_bytes; + mz_ulong orig_total_in, orig_total_out; + int mz_status = MZ_OK; + + if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) + return MZ_STREAM_ERROR; + if (!pStream->avail_out) + return MZ_BUF_ERROR; + + if (flush == MZ_PARTIAL_FLUSH) + flush = MZ_SYNC_FLUSH; + + if (((tdefl_compressor *)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE) + return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR; + + orig_total_in = pStream->total_in; + orig_total_out = pStream->total_out; + for (;;) + { + tdefl_status defl_status; + in_bytes = pStream->avail_in; + out_bytes = pStream->avail_out; + + defl_status = tdefl_compress((tdefl_compressor *)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush); + pStream->next_in += (mz_uint)in_bytes; + pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; + pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state); + + pStream->next_out += (mz_uint)out_bytes; + pStream->avail_out -= (mz_uint)out_bytes; + pStream->total_out += (mz_uint)out_bytes; + + if (defl_status < 0) + { + mz_status = MZ_STREAM_ERROR; + break; + } + else if (defl_status == TDEFL_STATUS_DONE) + { + mz_status = MZ_STREAM_END; + break; + } + else if (!pStream->avail_out) + break; + else if ((!pStream->avail_in) && (flush != MZ_FINISH)) + { + if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out)) + break; + return MZ_BUF_ERROR; /* Can't make forward progress without some input. + */ + } + } + return mz_status; +} + +int mz_deflateEnd(mz_streamp pStream) +{ + if (!pStream) + return MZ_STREAM_ERROR; + if (pStream->state) + { + pStream->zfree(pStream->opaque, pStream->state); + pStream->state = NULL; + } + return MZ_OK; +} + +mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len) +{ + (void)pStream; + /* This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) */ + return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5); +} + +int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level) +{ + int status; + mz_stream stream; + memset(&stream, 0, sizeof(stream)); + + /* In case mz_ulong is 64-bits (argh I hate longs). */ + if ((source_len | *pDest_len) > 0xFFFFFFFFU) + return MZ_PARAM_ERROR; + + stream.next_in = pSource; + stream.avail_in = (mz_uint32)source_len; + stream.next_out = pDest; + stream.avail_out = (mz_uint32) * pDest_len; + + status = mz_deflateInit(&stream, level); + if (status != MZ_OK) + return status; + + status = mz_deflate(&stream, MZ_FINISH); + if (status != MZ_STREAM_END) + { + mz_deflateEnd(&stream); + return (status == MZ_OK) ? MZ_BUF_ERROR : status; + } + + *pDest_len = stream.total_out; + return mz_deflateEnd(&stream); +} + +int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) +{ + return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION); +} + +mz_ulong mz_compressBound(mz_ulong source_len) +{ + return mz_deflateBound(NULL, source_len); +} + +typedef struct +{ + tinfl_decompressor m_decomp; + mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; + int m_window_bits; + mz_uint8 m_dict[TINFL_LZ_DICT_SIZE]; + tinfl_status m_last_status; +} inflate_state; + +int mz_inflateInit2(mz_streamp pStream, int window_bits) +{ + inflate_state *pDecomp; + if (!pStream) + return MZ_STREAM_ERROR; + if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) + return MZ_PARAM_ERROR; + + pStream->data_type = 0; + pStream->adler = 0; + pStream->msg = NULL; + pStream->total_in = 0; + pStream->total_out = 0; + pStream->reserved = 0; + if (!pStream->zalloc) + pStream->zalloc = miniz_def_alloc_func; + if (!pStream->zfree) + pStream->zfree = miniz_def_free_func; + + pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state)); + if (!pDecomp) + return MZ_MEM_ERROR; + + pStream->state = (struct mz_internal_state *)pDecomp; + + tinfl_init(&pDecomp->m_decomp); + pDecomp->m_dict_ofs = 0; + pDecomp->m_dict_avail = 0; + pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT; + pDecomp->m_first_call = 1; + pDecomp->m_has_flushed = 0; + pDecomp->m_window_bits = window_bits; + + return MZ_OK; +} + +int mz_inflateInit(mz_streamp pStream) +{ + return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS); +} + +int mz_inflate(mz_streamp pStream, int flush) +{ + inflate_state *pState; + mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32; + size_t in_bytes, out_bytes, orig_avail_in; + tinfl_status status; + + if ((!pStream) || (!pStream->state)) + return MZ_STREAM_ERROR; + if (flush == MZ_PARTIAL_FLUSH) + flush = MZ_SYNC_FLUSH; + if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) + return MZ_STREAM_ERROR; + + pState = (inflate_state *)pStream->state; + if (pState->m_window_bits > 0) + decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER; + orig_avail_in = pStream->avail_in; + + first_call = pState->m_first_call; + pState->m_first_call = 0; + if (pState->m_last_status < 0) + return MZ_DATA_ERROR; + + if (pState->m_has_flushed && (flush != MZ_FINISH)) + return MZ_STREAM_ERROR; + pState->m_has_flushed |= (flush == MZ_FINISH); + + if ((flush == MZ_FINISH) && (first_call)) + { + /* MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. */ + decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; + in_bytes = pStream->avail_in; + out_bytes = pStream->avail_out; + status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags); + pState->m_last_status = status; + pStream->next_in += (mz_uint)in_bytes; + pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; + pStream->adler = tinfl_get_adler32(&pState->m_decomp); + pStream->next_out += (mz_uint)out_bytes; + pStream->avail_out -= (mz_uint)out_bytes; + pStream->total_out += (mz_uint)out_bytes; + + if (status < 0) + return MZ_DATA_ERROR; + else if (status != TINFL_STATUS_DONE) + { + pState->m_last_status = TINFL_STATUS_FAILED; + return MZ_BUF_ERROR; + } + return MZ_STREAM_END; + } + /* flush != MZ_FINISH then we must assume there's more input. */ + if (flush != MZ_FINISH) + decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT; + + if (pState->m_dict_avail) + { + n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); + memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); + pStream->next_out += n; + pStream->avail_out -= n; + pStream->total_out += n; + pState->m_dict_avail -= n; + pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); + return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; + } + + for (;;) + { + in_bytes = pStream->avail_in; + out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs; + + status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags); + pState->m_last_status = status; + + pStream->next_in += (mz_uint)in_bytes; + pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; + pStream->adler = tinfl_get_adler32(&pState->m_decomp); + + pState->m_dict_avail = (mz_uint)out_bytes; + + n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); + memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); + pStream->next_out += n; + pStream->avail_out -= n; + pStream->total_out += n; + pState->m_dict_avail -= n; + pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); + + if (status < 0) + return MZ_DATA_ERROR; /* Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). */ + else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in)) + return MZ_BUF_ERROR; /* Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. */ + else if (flush == MZ_FINISH) + { + /* The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. */ + if (status == TINFL_STATUS_DONE) + return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END; + /* status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. */ + else if (!pStream->avail_out) + return MZ_BUF_ERROR; + } + else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail)) + break; + } + + return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; +} + +int mz_inflateEnd(mz_streamp pStream) +{ + if (!pStream) + return MZ_STREAM_ERROR; + if (pStream->state) + { + pStream->zfree(pStream->opaque, pStream->state); + pStream->state = NULL; + } + return MZ_OK; +} + +int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) +{ + mz_stream stream; + int status; + memset(&stream, 0, sizeof(stream)); + + /* In case mz_ulong is 64-bits (argh I hate longs). */ + if ((source_len | *pDest_len) > 0xFFFFFFFFU) + return MZ_PARAM_ERROR; + + stream.next_in = pSource; + stream.avail_in = (mz_uint32)source_len; + stream.next_out = pDest; + stream.avail_out = (mz_uint32) * pDest_len; + + status = mz_inflateInit(&stream); + if (status != MZ_OK) + return status; + + status = mz_inflate(&stream, MZ_FINISH); + if (status != MZ_STREAM_END) + { + mz_inflateEnd(&stream); + return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status; + } + *pDest_len = stream.total_out; + + return mz_inflateEnd(&stream); +} + +const char *mz_error(int err) +{ + static struct + { + int m_err; + const char *m_pDesc; + } s_error_descs[] = + { + { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" }, + { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" } + }; + mz_uint i; + for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) + if (s_error_descs[i].m_err == err) + return s_error_descs[i].m_pDesc; + return NULL; +} + +#endif /*MINIZ_NO_ZLIB_APIS */ + +#ifdef __cplusplus +} +#endif + +/* + This is free and unencumbered software released into the public domain. + + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. + + In jurisdictions that recognize copyright laws, the author or authors + of this software dedicate any and all copyright interest in the + software to the public domain. We make this dedication for the benefit + of the public at large and to the detriment of our heirs and + successors. We intend this dedication to be an overt act of + relinquishment in perpetuity of all present and future rights to this + software under copyright law. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + + For more information, please refer to +*/ +/************************************************************************** + * + * Copyright 2013-2014 RAD Game Tools and Valve Software + * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + + + + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------- Low-level Compression (independent from all decompression API's) */ + +/* Purposely making these tables static for faster init and thread safety. */ +static const mz_uint16 s_tdefl_len_sym[256] = + { + 257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268, 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272, + 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276, 276, 276, 276, 276, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 285 + }; + +static const mz_uint8 s_tdefl_len_extra[256] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0 + }; + +static const mz_uint8 s_tdefl_small_dist_sym[512] = + { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17 + }; + +static const mz_uint8 s_tdefl_small_dist_extra[512] = + { + 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7 + }; + +static const mz_uint8 s_tdefl_large_dist_sym[128] = + { + 0, 0, 18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 + }; + +static const mz_uint8 s_tdefl_large_dist_extra[128] = + { + 0, 0, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13 + }; + +/* Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. */ +typedef struct +{ + mz_uint16 m_key, m_sym_index; +} tdefl_sym_freq; +static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq *pSyms0, tdefl_sym_freq *pSyms1) +{ + mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; + tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1; + MZ_CLEAR_OBJ(hist); + for (i = 0; i < num_syms; i++) + { + mz_uint freq = pSyms0[i].m_key; + hist[freq & 0xFF]++; + hist[256 + ((freq >> 8) & 0xFF)]++; + } + while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) + total_passes--; + for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) + { + const mz_uint32 *pHist = &hist[pass << 8]; + mz_uint offsets[256], cur_ofs = 0; + for (i = 0; i < 256; i++) + { + offsets[i] = cur_ofs; + cur_ofs += pHist[i]; + } + for (i = 0; i < num_syms; i++) + pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i]; + { + tdefl_sym_freq *t = pCur_syms; + pCur_syms = pNew_syms; + pNew_syms = t; + } + } + return pCur_syms; +} + +/* tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. */ +static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) +{ + int root, leaf, next, avbl, used, dpth; + if (n == 0) + return; + else if (n == 1) + { + A[0].m_key = 1; + return; + } + A[0].m_key += A[1].m_key; + root = 0; + leaf = 2; + for (next = 1; next < n - 1; next++) + { + if (leaf >= n || A[root].m_key < A[leaf].m_key) + { + A[next].m_key = A[root].m_key; + A[root++].m_key = (mz_uint16)next; + } + else + A[next].m_key = A[leaf++].m_key; + if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key)) + { + A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key); + A[root++].m_key = (mz_uint16)next; + } + else + A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key); + } + A[n - 2].m_key = 0; + for (next = n - 3; next >= 0; next--) + A[next].m_key = A[A[next].m_key].m_key + 1; + avbl = 1; + used = dpth = 0; + root = n - 2; + next = n - 1; + while (avbl > 0) + { + while (root >= 0 && (int)A[root].m_key == dpth) + { + used++; + root--; + } + while (avbl > used) + { + A[next--].m_key = (mz_uint16)(dpth); + avbl--; + } + avbl = 2 * used; + dpth++; + used = 0; + } +} + +/* Limits canonical Huffman code table's max code size. */ +enum +{ + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 +}; +static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size) +{ + int i; + mz_uint32 total = 0; + if (code_list_len <= 1) + return; + for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) + pNum_codes[max_code_size] += pNum_codes[i]; + for (i = max_code_size; i > 0; i--) + total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i)); + while (total != (1UL << max_code_size)) + { + pNum_codes[max_code_size]--; + for (i = max_code_size - 1; i > 0; i--) + if (pNum_codes[i]) + { + pNum_codes[i]--; + pNum_codes[i + 1] += 2; + break; + } + total--; + } +} + +static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table) +{ + int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; + mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; + MZ_CLEAR_OBJ(num_codes); + if (static_table) + { + for (i = 0; i < table_len; i++) + num_codes[d->m_huff_code_sizes[table_num][i]]++; + } + else + { + tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms; + int num_used_syms = 0; + const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0]; + for (i = 0; i < table_len; i++) + if (pSym_count[i]) + { + syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; + syms0[num_used_syms++].m_sym_index = (mz_uint16)i; + } + + pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); + tdefl_calculate_minimum_redundancy(pSyms, num_used_syms); + + for (i = 0; i < num_used_syms; i++) + num_codes[pSyms[i].m_key]++; + + tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit); + + MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); + MZ_CLEAR_OBJ(d->m_huff_codes[table_num]); + for (i = 1, j = num_used_syms; i <= code_size_limit; i++) + for (l = num_codes[i]; l > 0; l--) + d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i); + } + + next_code[1] = 0; + for (j = 0, i = 2; i <= code_size_limit; i++) + next_code[i] = j = ((j + num_codes[i - 1]) << 1); + + for (i = 0; i < table_len; i++) + { + mz_uint rev_code = 0, code, code_size; + if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) + continue; + code = next_code[code_size]++; + for (l = code_size; l > 0; l--, code >>= 1) + rev_code = (rev_code << 1) | (code & 1); + d->m_huff_codes[table_num][i] = (mz_uint16)rev_code; + } +} + +#define TDEFL_PUT_BITS(b, l) \ + do \ + { \ + mz_uint bits = b; \ + mz_uint len = l; \ + MZ_ASSERT(bits <= ((1U << len) - 1U)); \ + d->m_bit_buffer |= (bits << d->m_bits_in); \ + d->m_bits_in += len; \ + while (d->m_bits_in >= 8) \ + { \ + if (d->m_pOutput_buf < d->m_pOutput_buf_end) \ + *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \ + d->m_bit_buffer >>= 8; \ + d->m_bits_in -= 8; \ + } \ + } \ + MZ_MACRO_END + +#define TDEFL_RLE_PREV_CODE_SIZE() \ + { \ + if (rle_repeat_count) \ + { \ + if (rle_repeat_count < 3) \ + { \ + d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \ + while (rle_repeat_count--) \ + packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \ + } \ + else \ + { \ + d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); \ + packed_code_sizes[num_packed_code_sizes++] = 16; \ + packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \ + } \ + rle_repeat_count = 0; \ + } \ + } + +#define TDEFL_RLE_ZERO_CODE_SIZE() \ + { \ + if (rle_z_count) \ + { \ + if (rle_z_count < 3) \ + { \ + d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); \ + while (rle_z_count--) \ + packed_code_sizes[num_packed_code_sizes++] = 0; \ + } \ + else if (rle_z_count <= 10) \ + { \ + d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); \ + packed_code_sizes[num_packed_code_sizes++] = 17; \ + packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \ + } \ + else \ + { \ + d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); \ + packed_code_sizes[num_packed_code_sizes++] = 18; \ + packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \ + } \ + rle_z_count = 0; \ + } \ + } + +static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + +static void tdefl_start_dynamic_block(tdefl_compressor *d) +{ + int num_lit_codes, num_dist_codes, num_bit_lengths; + mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index; + mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF; + + d->m_huff_count[0][256] = 1; + + tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE); + tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE); + + for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) + if (d->m_huff_code_sizes[0][num_lit_codes - 1]) + break; + for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) + if (d->m_huff_code_sizes[1][num_dist_codes - 1]) + break; + + memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes); + memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes); + total_code_sizes_to_pack = num_lit_codes + num_dist_codes; + num_packed_code_sizes = 0; + rle_z_count = 0; + rle_repeat_count = 0; + + memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2); + for (i = 0; i < total_code_sizes_to_pack; i++) + { + mz_uint8 code_size = code_sizes_to_pack[i]; + if (!code_size) + { + TDEFL_RLE_PREV_CODE_SIZE(); + if (++rle_z_count == 138) + { + TDEFL_RLE_ZERO_CODE_SIZE(); + } + } + else + { + TDEFL_RLE_ZERO_CODE_SIZE(); + if (code_size != prev_code_size) + { + TDEFL_RLE_PREV_CODE_SIZE(); + d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); + packed_code_sizes[num_packed_code_sizes++] = code_size; + } + else if (++rle_repeat_count == 6) + { + TDEFL_RLE_PREV_CODE_SIZE(); + } + } + prev_code_size = code_size; + } + if (rle_repeat_count) + { + TDEFL_RLE_PREV_CODE_SIZE(); + } + else + { + TDEFL_RLE_ZERO_CODE_SIZE(); + } + + tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE); + + TDEFL_PUT_BITS(2, 2); + + TDEFL_PUT_BITS(num_lit_codes - 257, 5); + TDEFL_PUT_BITS(num_dist_codes - 1, 5); + + for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) + if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) + break; + num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); + TDEFL_PUT_BITS(num_bit_lengths - 4, 4); + for (i = 0; (int)i < num_bit_lengths; i++) + TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3); + + for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;) + { + mz_uint code = packed_code_sizes[packed_code_sizes_index++]; + MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2); + TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]); + if (code >= 16) + TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]); + } +} + +static void tdefl_start_static_block(tdefl_compressor *d) +{ + mz_uint i; + mz_uint8 *p = &d->m_huff_code_sizes[0][0]; + + for (i = 0; i <= 143; ++i) + *p++ = 8; + for (; i <= 255; ++i) + *p++ = 9; + for (; i <= 279; ++i) + *p++ = 7; + for (; i <= 287; ++i) + *p++ = 8; + + memset(d->m_huff_code_sizes[1], 5, 32); + + tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE); + tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE); + + TDEFL_PUT_BITS(1, 2); +} + +static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES &&MINIZ_LITTLE_ENDIAN &&MINIZ_HAS_64BIT_REGISTERS +static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) +{ + mz_uint flags; + mz_uint8 *pLZ_codes; + mz_uint8 *pOutput_buf = d->m_pOutput_buf; + mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf; + mz_uint64 bit_buffer = d->m_bit_buffer; + mz_uint bits_in = d->m_bits_in; + +#define TDEFL_PUT_BITS_FAST(b, l) \ + { \ + bit_buffer |= (((mz_uint64)(b)) << bits_in); \ + bits_in += (l); \ + } + + flags = 1; + for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1) + { + if (flags == 1) + flags = *pLZ_codes++ | 0x100; + + if (flags & 1) + { + mz_uint s0, s1, n0, n1, sym, num_extra_bits; + mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); + pLZ_codes += 3; + + MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); + + /* This sequence coaxes MSVC into using cmov's vs. jmp's. */ + s0 = s_tdefl_small_dist_sym[match_dist & 511]; + n0 = s_tdefl_small_dist_extra[match_dist & 511]; + s1 = s_tdefl_large_dist_sym[match_dist >> 8]; + n1 = s_tdefl_large_dist_extra[match_dist >> 8]; + sym = (match_dist < 512) ? s0 : s1; + num_extra_bits = (match_dist < 512) ? n0 : n1; + + MZ_ASSERT(d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); + } + else + { + mz_uint lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + + if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) + { + flags >>= 1; + lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + + if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) + { + flags >>= 1; + lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + } + } + } + + if (pOutput_buf >= d->m_pOutput_buf_end) + return MZ_FALSE; + + *(mz_uint64 *)pOutput_buf = bit_buffer; + pOutput_buf += (bits_in >> 3); + bit_buffer >>= (bits_in & ~7); + bits_in &= 7; + } + +#undef TDEFL_PUT_BITS_FAST + + d->m_pOutput_buf = pOutput_buf; + d->m_bits_in = 0; + d->m_bit_buffer = 0; + + while (bits_in) + { + mz_uint32 n = MZ_MIN(bits_in, 16); + TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n); + bit_buffer >>= n; + bits_in -= n; + } + + TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); + + return (d->m_pOutput_buf < d->m_pOutput_buf_end); +} +#else +static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) +{ + mz_uint flags; + mz_uint8 *pLZ_codes; + + flags = 1; + for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1) + { + if (flags == 1) + flags = *pLZ_codes++ | 0x100; + if (flags & 1) + { + mz_uint sym, num_extra_bits; + mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); + pLZ_codes += 3; + + MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); + + if (match_dist < 512) + { + sym = s_tdefl_small_dist_sym[match_dist]; + num_extra_bits = s_tdefl_small_dist_extra[match_dist]; + } + else + { + sym = s_tdefl_large_dist_sym[match_dist >> 8]; + num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8]; + } + MZ_ASSERT(d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); + } + else + { + mz_uint lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + } + } + + TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); + + return (d->m_pOutput_buf < d->m_pOutput_buf_end); +} +#endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS */ + +static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) +{ + if (static_block) + tdefl_start_static_block(d); + else + tdefl_start_dynamic_block(d); + return tdefl_compress_lz_codes(d); +} + +static int tdefl_flush_block(tdefl_compressor *d, int flush) +{ + mz_uint saved_bit_buf, saved_bits_in; + mz_uint8 *pSaved_output_buf; + mz_bool comp_block_succeeded = MZ_FALSE; + int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size; + mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf; + + d->m_pOutput_buf = pOutput_buf_start; + d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16; + + MZ_ASSERT(!d->m_output_flush_remaining); + d->m_output_flush_ofs = 0; + d->m_output_flush_remaining = 0; + + *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left); + d->m_pLZ_code_buf -= (d->m_num_flags_left == 8); + + if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) + { + TDEFL_PUT_BITS(0x78, 8); + TDEFL_PUT_BITS(0x01, 8); + } + + TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1); + + pSaved_output_buf = d->m_pOutput_buf; + saved_bit_buf = d->m_bit_buffer; + saved_bits_in = d->m_bits_in; + + if (!use_raw_block) + comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48)); + + /* If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. */ + if (((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) && + ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size)) + { + mz_uint i; + d->m_pOutput_buf = pSaved_output_buf; + d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; + TDEFL_PUT_BITS(0, 2); + if (d->m_bits_in) + { + TDEFL_PUT_BITS(0, 8 - d->m_bits_in); + } + for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) + { + TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16); + } + for (i = 0; i < d->m_total_lz_bytes; ++i) + { + TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8); + } + } + /* Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. */ + else if (!comp_block_succeeded) + { + d->m_pOutput_buf = pSaved_output_buf; + d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; + tdefl_compress_block(d, MZ_TRUE); + } + + if (flush) + { + if (flush == TDEFL_FINISH) + { + if (d->m_bits_in) + { + TDEFL_PUT_BITS(0, 8 - d->m_bits_in); + } + if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) + { + mz_uint i, a = d->m_adler32; + for (i = 0; i < 4; i++) + { + TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); + a <<= 8; + } + } + } + else + { + mz_uint i, z = 0; + TDEFL_PUT_BITS(0, 3); + if (d->m_bits_in) + { + TDEFL_PUT_BITS(0, 8 - d->m_bits_in); + } + for (i = 2; i; --i, z ^= 0xFFFF) + { + TDEFL_PUT_BITS(z & 0xFFFF, 16); + } + } + } + + MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end); + + memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); + memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); + + d->m_pLZ_code_buf = d->m_lz_code_buf + 1; + d->m_pLZ_flags = d->m_lz_code_buf; + d->m_num_flags_left = 8; + d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; + d->m_total_lz_bytes = 0; + d->m_block_index++; + + if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) + { + if (d->m_pPut_buf_func) + { + *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; + if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user)) + return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED); + } + else if (pOutput_buf_start == d->m_output_buf) + { + int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs)); + memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy); + d->m_out_buf_ofs += bytes_to_copy; + if ((n -= bytes_to_copy) != 0) + { + d->m_output_flush_ofs = bytes_to_copy; + d->m_output_flush_remaining = n; + } + } + else + { + d->m_out_buf_ofs += n; + } + } + + return d->m_output_flush_remaining; +} + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES +#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16 *)(p) +static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) +{ + mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; + mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; + const mz_uint16 *s = (const mz_uint16 *)(d->m_dict + pos), *p, *q; + mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s); + MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); + if (max_match_len <= match_len) + return; + for (;;) + { + for (;;) + { + if (--num_probes_left == 0) + return; +#define TDEFL_PROBE \ + next_probe_pos = d->m_next[probe_pos]; \ + if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \ + return; \ + probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ + if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) \ + break; + TDEFL_PROBE; + TDEFL_PROBE; + TDEFL_PROBE; + } + if (!dist) + break; + q = (const mz_uint16 *)(d->m_dict + probe_pos); + if (TDEFL_READ_UNALIGNED_WORD(q) != s01) + continue; + p = s; + probe_len = 32; + do + { + } while ((TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && + (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0)); + if (!probe_len) + { + *pMatch_dist = dist; + *pMatch_len = MZ_MIN(max_match_len, (mz_uint)TDEFL_MAX_MATCH_LEN); + break; + } + else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q)) > match_len) + { + *pMatch_dist = dist; + if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) + break; + c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]); + } + } +} +#else +static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) +{ + mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; + mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; + const mz_uint8 *s = d->m_dict + pos, *p, *q; + mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1]; + MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); + if (max_match_len <= match_len) + return; + for (;;) + { + for (;;) + { + if (--num_probes_left == 0) + return; +#define TDEFL_PROBE \ + next_probe_pos = d->m_next[probe_pos]; \ + if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \ + return; \ + probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ + if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) \ + break; + TDEFL_PROBE; + TDEFL_PROBE; + TDEFL_PROBE; + } + if (!dist) + break; + p = s; + q = d->m_dict + probe_pos; + for (probe_len = 0; probe_len < max_match_len; probe_len++) + if (*p++ != *q++) + break; + if (probe_len > match_len) + { + *pMatch_dist = dist; + if ((*pMatch_len = match_len = probe_len) == max_match_len) + return; + c0 = d->m_dict[pos + match_len]; + c1 = d->m_dict[pos + match_len - 1]; + } + } +} +#endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES */ + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES &&MINIZ_LITTLE_ENDIAN +static mz_bool tdefl_compress_fast(tdefl_compressor *d) +{ + /* Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. */ + mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left; + mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags; + mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; + + while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) + { + const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096; + mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; + mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size); + d->m_src_buf_left -= num_bytes_to_process; + lookahead_size += num_bytes_to_process; + + while (num_bytes_to_process) + { + mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process); + memcpy(d->m_dict + dst_pos, d->m_pSrc, n); + if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) + memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos)); + d->m_pSrc += n; + dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK; + num_bytes_to_process -= n; + } + + dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size); + if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) + break; + + while (lookahead_size >= 4) + { + mz_uint cur_match_dist, cur_match_len = 1; + mz_uint8 *pCur_dict = d->m_dict + cur_pos; + mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF; + mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK; + mz_uint probe_pos = d->m_hash[hash]; + d->m_hash[hash] = (mz_uint16)lookahead_pos; + + if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) + { + const mz_uint16 *p = (const mz_uint16 *)pCur_dict; + const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos); + mz_uint32 probe_len = 32; + do + { + } while ((TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && + (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0)); + cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q); + if (!probe_len) + cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0; + + if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U))) + { + cur_match_len = 1; + *pLZ_code_buf++ = (mz_uint8)first_trigram; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + d->m_huff_count[0][(mz_uint8)first_trigram]++; + } + else + { + mz_uint32 s0, s1; + cur_match_len = MZ_MIN(cur_match_len, lookahead_size); + + MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE)); + + cur_match_dist--; + + pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN); + *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist; + pLZ_code_buf += 3; + *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80); + + s0 = s_tdefl_small_dist_sym[cur_match_dist & 511]; + s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8]; + d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++; + + d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++; + } + } + else + { + *pLZ_code_buf++ = (mz_uint8)first_trigram; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + d->m_huff_count[0][(mz_uint8)first_trigram]++; + } + + if (--num_flags_left == 0) + { + num_flags_left = 8; + pLZ_flags = pLZ_code_buf++; + } + + total_lz_bytes += cur_match_len; + lookahead_pos += cur_match_len; + dict_size = MZ_MIN(dict_size + cur_match_len, (mz_uint)TDEFL_LZ_DICT_SIZE); + cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK; + MZ_ASSERT(lookahead_size >= cur_match_len); + lookahead_size -= cur_match_len; + + if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) + { + int n; + d->m_lookahead_pos = lookahead_pos; + d->m_lookahead_size = lookahead_size; + d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; + d->m_pLZ_code_buf = pLZ_code_buf; + d->m_pLZ_flags = pLZ_flags; + d->m_num_flags_left = num_flags_left; + if ((n = tdefl_flush_block(d, 0)) != 0) + return (n < 0) ? MZ_FALSE : MZ_TRUE; + total_lz_bytes = d->m_total_lz_bytes; + pLZ_code_buf = d->m_pLZ_code_buf; + pLZ_flags = d->m_pLZ_flags; + num_flags_left = d->m_num_flags_left; + } + } + + while (lookahead_size) + { + mz_uint8 lit = d->m_dict[cur_pos]; + + total_lz_bytes++; + *pLZ_code_buf++ = lit; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + if (--num_flags_left == 0) + { + num_flags_left = 8; + pLZ_flags = pLZ_code_buf++; + } + + d->m_huff_count[0][lit]++; + + lookahead_pos++; + dict_size = MZ_MIN(dict_size + 1, (mz_uint)TDEFL_LZ_DICT_SIZE); + cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; + lookahead_size--; + + if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) + { + int n; + d->m_lookahead_pos = lookahead_pos; + d->m_lookahead_size = lookahead_size; + d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; + d->m_pLZ_code_buf = pLZ_code_buf; + d->m_pLZ_flags = pLZ_flags; + d->m_num_flags_left = num_flags_left; + if ((n = tdefl_flush_block(d, 0)) != 0) + return (n < 0) ? MZ_FALSE : MZ_TRUE; + total_lz_bytes = d->m_total_lz_bytes; + pLZ_code_buf = d->m_pLZ_code_buf; + pLZ_flags = d->m_pLZ_flags; + num_flags_left = d->m_num_flags_left; + } + } + } + + d->m_lookahead_pos = lookahead_pos; + d->m_lookahead_size = lookahead_size; + d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; + d->m_pLZ_code_buf = pLZ_code_buf; + d->m_pLZ_flags = pLZ_flags; + d->m_num_flags_left = num_flags_left; + return MZ_TRUE; +} +#endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */ + +static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit) +{ + d->m_total_lz_bytes++; + *d->m_pLZ_code_buf++ = lit; + *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); + if (--d->m_num_flags_left == 0) + { + d->m_num_flags_left = 8; + d->m_pLZ_flags = d->m_pLZ_code_buf++; + } + d->m_huff_count[0][lit]++; +} + +static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist) +{ + mz_uint32 s0, s1; + + MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE)); + + d->m_total_lz_bytes += match_len; + + d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN); + + match_dist -= 1; + d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF); + d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); + d->m_pLZ_code_buf += 3; + + *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); + if (--d->m_num_flags_left == 0) + { + d->m_num_flags_left = 8; + d->m_pLZ_flags = d->m_pLZ_code_buf++; + } + + s0 = s_tdefl_small_dist_sym[match_dist & 511]; + s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127]; + d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++; + + if (match_len >= TDEFL_MIN_MATCH_LEN) + d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++; +} + +static mz_bool tdefl_compress_normal(tdefl_compressor *d) +{ + const mz_uint8 *pSrc = d->m_pSrc; + size_t src_buf_left = d->m_src_buf_left; + tdefl_flush flush = d->m_flush; + + while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) + { + mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos; + /* Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. */ + if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) + { + mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2; + mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]; + mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size); + const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process; + src_buf_left -= num_bytes_to_process; + d->m_lookahead_size += num_bytes_to_process; + while (pSrc != pSrc_end) + { + mz_uint8 c = *pSrc++; + d->m_dict[dst_pos] = c; + if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) + d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; + hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); + d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; + d->m_hash[hash] = (mz_uint16)(ins_pos); + dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; + ins_pos++; + } + } + else + { + while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) + { + mz_uint8 c = *pSrc++; + mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; + src_buf_left--; + d->m_dict[dst_pos] = c; + if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) + d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; + if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) + { + mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2; + mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); + d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; + d->m_hash[hash] = (mz_uint16)(ins_pos); + } + } + } + d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size); + if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) + break; + + /* Simple lazy/greedy parsing state machine. */ + len_to_move = 1; + cur_match_dist = 0; + cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); + cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; + if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) + { + if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) + { + mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK]; + cur_match_len = 0; + while (cur_match_len < d->m_lookahead_size) + { + if (d->m_dict[cur_pos + cur_match_len] != c) + break; + cur_match_len++; + } + if (cur_match_len < TDEFL_MIN_MATCH_LEN) + cur_match_len = 0; + else + cur_match_dist = 1; + } + } + else + { + tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len); + } + if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) + { + cur_match_dist = cur_match_len = 0; + } + if (d->m_saved_match_len) + { + if (cur_match_len > d->m_saved_match_len) + { + tdefl_record_literal(d, (mz_uint8)d->m_saved_lit); + if (cur_match_len >= 128) + { + tdefl_record_match(d, cur_match_len, cur_match_dist); + d->m_saved_match_len = 0; + len_to_move = cur_match_len; + } + else + { + d->m_saved_lit = d->m_dict[cur_pos]; + d->m_saved_match_dist = cur_match_dist; + d->m_saved_match_len = cur_match_len; + } + } + else + { + tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist); + len_to_move = d->m_saved_match_len - 1; + d->m_saved_match_len = 0; + } + } + else if (!cur_match_dist) + tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]); + else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128)) + { + tdefl_record_match(d, cur_match_len, cur_match_dist); + len_to_move = cur_match_len; + } + else + { + d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; + d->m_saved_match_dist = cur_match_dist; + d->m_saved_match_len = cur_match_len; + } + /* Move the lookahead forward by len_to_move bytes. */ + d->m_lookahead_pos += len_to_move; + MZ_ASSERT(d->m_lookahead_size >= len_to_move); + d->m_lookahead_size -= len_to_move; + d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, (mz_uint)TDEFL_LZ_DICT_SIZE); + /* Check if it's time to flush the current LZ codes to the internal output buffer. */ + if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) || + ((d->m_total_lz_bytes > 31 * 1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))) + { + int n; + d->m_pSrc = pSrc; + d->m_src_buf_left = src_buf_left; + if ((n = tdefl_flush_block(d, 0)) != 0) + return (n < 0) ? MZ_FALSE : MZ_TRUE; + } + } + + d->m_pSrc = pSrc; + d->m_src_buf_left = src_buf_left; + return MZ_TRUE; +} + +static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) +{ + if (d->m_pIn_buf_size) + { + *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; + } + + if (d->m_pOut_buf_size) + { + size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining); + memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n); + d->m_output_flush_ofs += (mz_uint)n; + d->m_output_flush_remaining -= (mz_uint)n; + d->m_out_buf_ofs += n; + + *d->m_pOut_buf_size = d->m_out_buf_ofs; + } + + return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY; +} + +tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush) +{ + if (!d) + { + if (pIn_buf_size) + *pIn_buf_size = 0; + if (pOut_buf_size) + *pOut_buf_size = 0; + return TDEFL_STATUS_BAD_PARAM; + } + + d->m_pIn_buf = pIn_buf; + d->m_pIn_buf_size = pIn_buf_size; + d->m_pOut_buf = pOut_buf; + d->m_pOut_buf_size = pOut_buf_size; + d->m_pSrc = (const mz_uint8 *)(pIn_buf); + d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0; + d->m_out_buf_ofs = 0; + d->m_flush = flush; + + if (((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) || + (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf)) + { + if (pIn_buf_size) + *pIn_buf_size = 0; + if (pOut_buf_size) + *pOut_buf_size = 0; + return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM); + } + d->m_wants_to_finish |= (flush == TDEFL_FINISH); + + if ((d->m_output_flush_remaining) || (d->m_finished)) + return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES &&MINIZ_LITTLE_ENDIAN + if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) && + ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) && + ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0)) + { + if (!tdefl_compress_fast(d)) + return d->m_prev_return_status; + } + else +#endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */ + { + if (!tdefl_compress_normal(d)) + return d->m_prev_return_status; + } + + if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf)) + d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf); + + if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining)) + { + if (tdefl_flush_block(d, flush) < 0) + return d->m_prev_return_status; + d->m_finished = (flush == TDEFL_FINISH); + if (flush == TDEFL_FULL_FLUSH) + { + MZ_CLEAR_OBJ(d->m_hash); + MZ_CLEAR_OBJ(d->m_next); + d->m_dict_size = 0; + } + } + + return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); +} + +tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush) +{ + MZ_ASSERT(d->m_pPut_buf_func); + return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush); +} + +tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) +{ + d->m_pPut_buf_func = pPut_buf_func; + d->m_pPut_buf_user = pPut_buf_user; + d->m_flags = (mz_uint)(flags); + d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; + d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0; + d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3; + if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) + MZ_CLEAR_OBJ(d->m_hash); + d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0; + d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0; + d->m_pLZ_code_buf = d->m_lz_code_buf + 1; + d->m_pLZ_flags = d->m_lz_code_buf; + d->m_num_flags_left = 8; + d->m_pOutput_buf = d->m_output_buf; + d->m_pOutput_buf_end = d->m_output_buf; + d->m_prev_return_status = TDEFL_STATUS_OKAY; + d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; + d->m_adler32 = 1; + d->m_pIn_buf = NULL; + d->m_pOut_buf = NULL; + d->m_pIn_buf_size = NULL; + d->m_pOut_buf_size = NULL; + d->m_flush = TDEFL_NO_FLUSH; + d->m_pSrc = NULL; + d->m_src_buf_left = 0; + d->m_out_buf_ofs = 0; + memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); + memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); + return TDEFL_STATUS_OKAY; +} + +tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) +{ + return d->m_prev_return_status; +} + +mz_uint32 tdefl_get_adler32(tdefl_compressor *d) +{ + return d->m_adler32; +} + +mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) +{ + tdefl_compressor *pComp; + mz_bool succeeded; + if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) + return MZ_FALSE; + pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); + if (!pComp) + return MZ_FALSE; + succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY); + succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE); + MZ_FREE(pComp); + return succeeded; +} + +typedef struct +{ + size_t m_size, m_capacity; + mz_uint8 *m_pBuf; + mz_bool m_expandable; +} tdefl_output_buffer; + +static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser) +{ + tdefl_output_buffer *p = (tdefl_output_buffer *)pUser; + size_t new_size = p->m_size + len; + if (new_size > p->m_capacity) + { + size_t new_capacity = p->m_capacity; + mz_uint8 *pNew_buf; + if (!p->m_expandable) + return MZ_FALSE; + do + { + new_capacity = MZ_MAX(128U, new_capacity << 1U); + } while (new_size > new_capacity); + pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity); + if (!pNew_buf) + return MZ_FALSE; + p->m_pBuf = pNew_buf; + p->m_capacity = new_capacity; + } + memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len); + p->m_size = new_size; + return MZ_TRUE; +} + +void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) +{ + tdefl_output_buffer out_buf; + MZ_CLEAR_OBJ(out_buf); + if (!pOut_len) + return nullptr; + else + *pOut_len = 0; + out_buf.m_expandable = MZ_TRUE; + if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) + return NULL; + *pOut_len = out_buf.m_size; + return out_buf.m_pBuf; +} + +size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) +{ + tdefl_output_buffer out_buf; + MZ_CLEAR_OBJ(out_buf); + if (!pOut_buf) + return 0; + out_buf.m_pBuf = (mz_uint8 *)pOut_buf; + out_buf.m_capacity = out_buf_len; + if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) + return 0; + return out_buf.m_size; +} + +#ifndef MINIZ_NO_ZLIB_APIS +static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; + +/* level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). */ +mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy) +{ + mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); + if (window_bits > 0) + comp_flags |= TDEFL_WRITE_ZLIB_HEADER; + + if (!level) + comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; + else if (strategy == MZ_FILTERED) + comp_flags |= TDEFL_FILTER_MATCHES; + else if (strategy == MZ_HUFFMAN_ONLY) + comp_flags &= ~TDEFL_MAX_PROBES_MASK; + else if (strategy == MZ_FIXED) + comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS; + else if (strategy == MZ_RLE) + comp_flags |= TDEFL_RLE_MATCHES; + + return comp_flags; +} +#endif /*MINIZ_NO_ZLIB_APIS */ + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4204) /* nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) */ +#endif + +/* Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at + http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/. + This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck. */ +void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip) +{ + /* Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. */ + static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; + tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); + tdefl_output_buffer out_buf; + int i, bpl = w * num_chans, y, z; + mz_uint32 c; + *pLen_out = 0; + if (!pComp) + return NULL; + MZ_CLEAR_OBJ(out_buf); + out_buf.m_expandable = MZ_TRUE; + out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h); + if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity))) + { + MZ_FREE(pComp); + return NULL; + } + /* write dummy header */ + for (z = 41; z; --z) + tdefl_output_buffer_putter(&z, 1, &out_buf); + /* compress image data */ + tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER); + for (y = 0; y < h; ++y) + { + tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); + tdefl_compress_buffer(pComp, (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); + } + if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) + { + MZ_FREE(pComp); + MZ_FREE(out_buf.m_pBuf); + return NULL; + } + /* write real header */ + *pLen_out = out_buf.m_size - 41; + { + static const mz_uint8 chans[] = { 0x00, 0x00, 0x04, 0x02, 0x06 }; + mz_uint8 pnghdr[41] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0, 0, (mz_uint8)(w >> 8), (mz_uint8)w, 0, 0, (mz_uint8)(h >> 8), (mz_uint8)h, 8, chans[num_chans], 0, 0, 0, 0, 0, 0, 0, + (mz_uint8)(*pLen_out >> 24), (mz_uint8)(*pLen_out >> 16), (mz_uint8)(*pLen_out >> 8), (mz_uint8) * pLen_out, 0x49, 0x44, 0x41, 0x54 }; + c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17); + for (i = 0; i < 4; ++i, c <<= 8) + ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24); + memcpy(out_buf.m_pBuf, pnghdr, 41); + } + /* write footer (IDAT CRC-32, followed by IEND chunk) */ + if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) + { + *pLen_out = 0; + MZ_FREE(pComp); + MZ_FREE(out_buf.m_pBuf); + return NULL; + } + c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, *pLen_out + 4); + for (i = 0; i < 4; ++i, c <<= 8) + (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24); + /* compute final size of file, grab compressed data buffer and return */ + *pLen_out += 57; + MZ_FREE(pComp); + return out_buf.m_pBuf; +} +void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out) +{ + /* Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out) */ + return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE); +} + +/* Allocate the tdefl_compressor and tinfl_decompressor structures in C so that */ +/* non-C language bindings to tdefL_ and tinfl_ API don't need to worry about */ +/* structure size and allocation mechanism. */ +tdefl_compressor *tdefl_compressor_alloc() +{ + return (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); +} + +void tdefl_compressor_free(tdefl_compressor *pComp) +{ + MZ_FREE(pComp); +} + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#ifdef __cplusplus +} +#endif +/************************************************************************** + * + * Copyright 2013-2014 RAD Game Tools and Valve Software + * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + + + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------- Low-level Decompression (completely independent from all compression API's) */ + +#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l) +#define TINFL_MEMSET(p, c, l) memset(p, c, l) + +#define TINFL_CR_BEGIN \ + switch (r->m_state) \ + { \ + case 0: +#define TINFL_CR_RETURN(state_index, result) \ + do \ + { \ + status = result; \ + r->m_state = state_index; \ + goto common_exit; \ + case state_index: \ + ; \ + } \ + MZ_MACRO_END +#define TINFL_CR_RETURN_FOREVER(state_index, result) \ + do \ + { \ + for (;;) \ + { \ + TINFL_CR_RETURN(state_index, result); \ + } \ + } \ + MZ_MACRO_END +#define TINFL_CR_FINISH } + +#define TINFL_GET_BYTE(state_index, c) \ + do \ + { \ + while (pIn_buf_cur >= pIn_buf_end) \ + { \ + TINFL_CR_RETURN(state_index, (decomp_flags &TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); \ + } \ + c = *pIn_buf_cur++; \ + } \ + MZ_MACRO_END + +#define TINFL_NEED_BITS(state_index, n) \ + do \ + { \ + mz_uint c; \ + TINFL_GET_BYTE(state_index, c); \ + bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \ + num_bits += 8; \ + } while (num_bits < (mz_uint)(n)) +#define TINFL_SKIP_BITS(state_index, n) \ + do \ + { \ + if (num_bits < (mz_uint)(n)) \ + { \ + TINFL_NEED_BITS(state_index, n); \ + } \ + bit_buf >>= (n); \ + num_bits -= (n); \ + } \ + MZ_MACRO_END +#define TINFL_GET_BITS(state_index, b, n) \ + do \ + { \ + if (num_bits < (mz_uint)(n)) \ + { \ + TINFL_NEED_BITS(state_index, n); \ + } \ + b = bit_buf & ((1 << (n)) - 1); \ + bit_buf >>= (n); \ + num_bits -= (n); \ + } \ + MZ_MACRO_END + +/* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. */ +/* It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a */ +/* Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the */ +/* bit buffer contains >=15 bits (deflate's max. Huffman code size). */ +#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \ + do \ + { \ + temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \ + if (temp >= 0) \ + { \ + code_len = temp >> 9; \ + if ((code_len) && (num_bits >= code_len)) \ + break; \ + } \ + else if (num_bits > TINFL_FAST_LOOKUP_BITS) \ + { \ + code_len = TINFL_FAST_LOOKUP_BITS; \ + do \ + { \ + temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \ + } while ((temp < 0) && (num_bits >= (code_len + 1))); \ + if (temp >= 0) \ + break; \ + } \ + TINFL_GET_BYTE(state_index, c); \ + bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \ + num_bits += 8; \ + } while (num_bits < 15); + +/* TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read */ +/* beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully */ +/* decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32. */ +/* The slow path is only executed at the very end of the input buffer. */ +/* v1.16: The original macro handled the case at the very end of the passed-in input buffer, but we also need to handle the case where the user passes in 1+zillion bytes */ +/* following the deflate data and our non-conservative read-ahead path won't kick in here on this code. This is much trickier. */ +#define TINFL_HUFF_DECODE(state_index, sym, pHuff) \ + do \ + { \ + int temp; \ + mz_uint code_len, c; \ + if (num_bits < 15) \ + { \ + if ((pIn_buf_end - pIn_buf_cur) < 2) \ + { \ + TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \ + } \ + else \ + { \ + bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); \ + pIn_buf_cur += 2; \ + num_bits += 16; \ + } \ + } \ + if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \ + code_len = temp >> 9, temp &= 511; \ + else \ + { \ + code_len = TINFL_FAST_LOOKUP_BITS; \ + do \ + { \ + temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \ + } while (temp < 0); \ + } \ + sym = temp; \ + bit_buf >>= code_len; \ + num_bits -= code_len; \ + } \ + MZ_MACRO_END + +tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags) +{ + static const int s_length_base[31] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 }; + static const int s_length_extra[31] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0 }; + static const int s_dist_base[32] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0 }; + static const int s_dist_extra[32] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 }; + static const mz_uint8 s_length_dezigzag[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + static const int s_min_table_sizes[3] = { 257, 1, 4 }; + + tinfl_status status = TINFL_STATUS_FAILED; + mz_uint32 num_bits, dist, counter, num_extra; + tinfl_bit_buf_t bit_buf; + const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size; + mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size; + size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t) - 1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start; + + /* Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). */ + if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) + { + *pIn_buf_size = *pOut_buf_size = 0; + return TINFL_STATUS_BAD_PARAM; + } + + num_bits = r->m_num_bits; + bit_buf = r->m_bit_buf; + dist = r->m_dist; + counter = r->m_counter; + num_extra = r->m_num_extra; + dist_from_out_buf_start = r->m_dist_from_out_buf_start; + TINFL_CR_BEGIN + + bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; + r->m_z_adler32 = r->m_check_adler32 = 1; + if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) + { + TINFL_GET_BYTE(1, r->m_zhdr0); + TINFL_GET_BYTE(2, r->m_zhdr1); + counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8)); + if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) + counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4))))); + if (counter) + { + TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); + } + } + + do + { + TINFL_GET_BITS(3, r->m_final, 3); + r->m_type = r->m_final >> 1; + if (r->m_type == 0) + { + TINFL_SKIP_BITS(5, num_bits & 7); + for (counter = 0; counter < 4; ++counter) + { + if (num_bits) + TINFL_GET_BITS(6, r->m_raw_header[counter], 8); + else + TINFL_GET_BYTE(7, r->m_raw_header[counter]); + } + if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) + { + TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); + } + while ((counter) && (num_bits)) + { + TINFL_GET_BITS(51, dist, 8); + while (pOut_buf_cur >= pOut_buf_end) + { + TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); + } + *pOut_buf_cur++ = (mz_uint8)dist; + counter--; + } + while (counter) + { + size_t n; + while (pOut_buf_cur >= pOut_buf_end) + { + TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); + } + while (pIn_buf_cur >= pIn_buf_end) + { + TINFL_CR_RETURN(38, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); + } + n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter); + TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); + pIn_buf_cur += n; + pOut_buf_cur += n; + counter -= (mz_uint)n; + } + } + else if (r->m_type == 3) + { + TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED); + } + else + { + if (r->m_type == 1) + { + mz_uint8 *p = r->m_tables[0].m_code_size; + mz_uint i; + r->m_table_sizes[0] = 288; + r->m_table_sizes[1] = 32; + TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32); + for (i = 0; i <= 143; ++i) + *p++ = 8; + for (; i <= 255; ++i) + *p++ = 9; + for (; i <= 279; ++i) + *p++ = 7; + for (; i <= 287; ++i) + *p++ = 8; + } + else + { + for (counter = 0; counter < 3; counter++) + { + TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); + r->m_table_sizes[counter] += s_min_table_sizes[counter]; + } + MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); + for (counter = 0; counter < r->m_table_sizes[2]; counter++) + { + mz_uint s; + TINFL_GET_BITS(14, s, 3); + r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; + } + r->m_table_sizes[2] = 19; + } + for (; (int)r->m_type >= 0; r->m_type--) + { + int tree_next, tree_cur; + tinfl_huff_table *pTable; + mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; + pTable = &r->m_tables[r->m_type]; + MZ_CLEAR_OBJ(total_syms); + MZ_CLEAR_OBJ(pTable->m_look_up); + MZ_CLEAR_OBJ(pTable->m_tree); + for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) + total_syms[pTable->m_code_size[i]]++; + used_syms = 0, total = 0; + next_code[0] = next_code[1] = 0; + for (i = 1; i <= 15; ++i) + { + used_syms += total_syms[i]; + next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); + } + if ((65536 != total) && (used_syms > 1)) + { + TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED); + } + for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index) + { + mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; + if (!code_size) + continue; + cur_code = next_code[code_size]++; + for (l = code_size; l > 0; l--, cur_code >>= 1) + rev_code = (rev_code << 1) | (cur_code & 1); + if (code_size <= TINFL_FAST_LOOKUP_BITS) + { + mz_int16 k = (mz_int16)((code_size << 9) | sym_index); + while (rev_code < TINFL_FAST_LOOKUP_SIZE) + { + pTable->m_look_up[rev_code] = k; + rev_code += (1 << code_size); + } + continue; + } + if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) + { + pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; + tree_cur = tree_next; + tree_next -= 2; + } + rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1); + for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) + { + tree_cur -= ((rev_code >>= 1) & 1); + if (!pTable->m_tree[-tree_cur - 1]) + { + pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; + tree_cur = tree_next; + tree_next -= 2; + } + else + tree_cur = pTable->m_tree[-tree_cur - 1]; + } + tree_cur -= ((rev_code >>= 1) & 1); + pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index; + } + if (r->m_type == 2) + { + for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);) + { + mz_uint s; + TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); + if (dist < 16) + { + r->m_len_codes[counter++] = (mz_uint8)dist; + continue; + } + if ((dist == 16) && (!counter)) + { + TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED); + } + num_extra = "\02\03\07"[dist - 16]; + TINFL_GET_BITS(18, s, num_extra); + s += "\03\03\013"[dist - 16]; + TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); + counter += s; + } + if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) + { + TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED); + } + TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); + TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]); + } + } + for (;;) + { + mz_uint8 *pSrc; + for (;;) + { + if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2)) + { + TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]); + if (counter >= 256) + break; + while (pOut_buf_cur >= pOut_buf_end) + { + TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); + } + *pOut_buf_cur++ = (mz_uint8)counter; + } + else + { + int sym2; + mz_uint code_len; +#if TINFL_USE_64BIT_BITBUF + if (num_bits < 30) + { + bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); + pIn_buf_cur += 4; + num_bits += 32; + } +#else + if (num_bits < 15) + { + bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); + pIn_buf_cur += 2; + num_bits += 16; + } +#endif + if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) + code_len = sym2 >> 9; + else + { + code_len = TINFL_FAST_LOOKUP_BITS; + do + { + sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; + } while (sym2 < 0); + } + counter = sym2; + bit_buf >>= code_len; + num_bits -= code_len; + if (counter & 256) + break; + +#if !TINFL_USE_64BIT_BITBUF + if (num_bits < 15) + { + bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); + pIn_buf_cur += 2; + num_bits += 16; + } +#endif + if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) + code_len = sym2 >> 9; + else + { + code_len = TINFL_FAST_LOOKUP_BITS; + do + { + sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; + } while (sym2 < 0); + } + bit_buf >>= code_len; + num_bits -= code_len; + + pOut_buf_cur[0] = (mz_uint8)counter; + if (sym2 & 256) + { + pOut_buf_cur++; + counter = sym2; + break; + } + pOut_buf_cur[1] = (mz_uint8)sym2; + pOut_buf_cur += 2; + } + } + if ((counter &= 511) == 256) + break; + + num_extra = s_length_extra[counter - 257]; + counter = s_length_base[counter - 257]; + if (num_extra) + { + mz_uint extra_bits; + TINFL_GET_BITS(25, extra_bits, num_extra); + counter += extra_bits; + } + + TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]); + num_extra = s_dist_extra[dist]; + dist = s_dist_base[dist]; + if (num_extra) + { + mz_uint extra_bits; + TINFL_GET_BITS(27, extra_bits, num_extra); + dist += extra_bits; + } + + dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start; + if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) + { + TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED); + } + + pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask); + + if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) + { + while (counter--) + { + while (pOut_buf_cur >= pOut_buf_end) + { + TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); + } + *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask]; + } + continue; + } +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES + else if ((counter >= 9) && (counter <= dist)) + { + const mz_uint8 *pSrc_end = pSrc + (counter & ~7); + do + { + ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0]; + ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1]; + pOut_buf_cur += 8; + } while ((pSrc += 8) < pSrc_end); + if ((counter &= 7) < 3) + { + if (counter) + { + pOut_buf_cur[0] = pSrc[0]; + if (counter > 1) + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur += counter; + } + continue; + } + } +#endif + do + { + pOut_buf_cur[0] = pSrc[0]; + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur[2] = pSrc[2]; + pOut_buf_cur += 3; + pSrc += 3; + } while ((int)(counter -= 3) > 2); + if ((int)counter > 0) + { + pOut_buf_cur[0] = pSrc[0]; + if ((int)counter > 1) + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur += counter; + } + } + } + } while (!(r->m_final & 1)); + + /* Ensure byte alignment and put back any bytes from the bitbuf if we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */ + /* I'm being super conservative here. A number of simplifications can be made to the byte alignment part, and the Adler32 check shouldn't ever need to worry about reading from the bitbuf now. */ + TINFL_SKIP_BITS(32, num_bits & 7); + while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8)) + { + --pIn_buf_cur; + num_bits -= 8; + } + bit_buf &= (tinfl_bit_buf_t)((1ULL << num_bits) - 1ULL); + MZ_ASSERT(!num_bits); /* if this assert fires then we've read beyond the end of non-deflate/zlib streams with following data (such as gzip streams). */ + + if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) + { + for (counter = 0; counter < 4; ++counter) + { + mz_uint s; + if (num_bits) + TINFL_GET_BITS(41, s, 8); + else + TINFL_GET_BYTE(42, s); + r->m_z_adler32 = (r->m_z_adler32 << 8) | s; + } + } + TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE); + + TINFL_CR_FINISH + +common_exit: + /* As long as we aren't telling the caller that we NEED more input to make forward progress: */ + /* Put back any bytes from the bitbuf in case we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */ + /* We need to be very careful here to NOT push back any bytes we definitely know we need to make forward progress, though, or we'll lock the caller up into an inf loop. */ + if ((status != TINFL_STATUS_NEEDS_MORE_INPUT) && (status != TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS)) + { + while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8)) + { + --pIn_buf_cur; + num_bits -= 8; + } + } + r->m_num_bits = num_bits; + r->m_bit_buf = bit_buf & (tinfl_bit_buf_t)((1ULL << num_bits) - 1ULL); + r->m_dist = dist; + r->m_counter = counter; + r->m_num_extra = num_extra; + r->m_dist_from_out_buf_start = dist_from_out_buf_start; + *pIn_buf_size = pIn_buf_cur - pIn_buf_next; + *pOut_buf_size = pOut_buf_cur - pOut_buf_next; + if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0)) + { + const mz_uint8 *ptr = pOut_buf_next; + size_t buf_len = *pOut_buf_size; + mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; + size_t block_len = buf_len % 5552; + while (buf_len) + { + for (i = 0; i + 7 < block_len; i += 8, ptr += 8) + { + s1 += ptr[0], s2 += s1; + s1 += ptr[1], s2 += s1; + s1 += ptr[2], s2 += s1; + s1 += ptr[3], s2 += s1; + s1 += ptr[4], s2 += s1; + s1 += ptr[5], s2 += s1; + s1 += ptr[6], s2 += s1; + s1 += ptr[7], s2 += s1; + } + for (; i < block_len; ++i) + s1 += *ptr++, s2 += s1; + s1 %= 65521U, s2 %= 65521U; + buf_len -= block_len; + block_len = 5552; + } + r->m_check_adler32 = (s2 << 16) + s1; + if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) + status = TINFL_STATUS_ADLER32_MISMATCH; + } + return status; +} + +/* Higher level helper functions. */ +void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) +{ + tinfl_decompressor decomp; + void *pBuf = NULL, *pNew_buf; + size_t src_buf_ofs = 0, out_buf_capacity = 0; + *pOut_len = 0; + tinfl_init(&decomp); + for (;;) + { + size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity; + tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL, &dst_buf_size, + (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); + if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) + { + MZ_FREE(pBuf); + *pOut_len = 0; + return NULL; + } + src_buf_ofs += src_buf_size; + *pOut_len += dst_buf_size; + if (status == TINFL_STATUS_DONE) + break; + new_out_buf_capacity = out_buf_capacity * 2; + if (new_out_buf_capacity < 128) + new_out_buf_capacity = 128; + pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity); + if (!pNew_buf) + { + MZ_FREE(pBuf); + *pOut_len = 0; + return NULL; + } + pBuf = pNew_buf; + out_buf_capacity = new_out_buf_capacity; + } + return pBuf; +} + +size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) +{ + tinfl_decompressor decomp; + tinfl_status status; + tinfl_init(&decomp); + status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf, &src_buf_len, (mz_uint8 *)pOut_buf, (mz_uint8 *)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); + return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len; +} + +int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) +{ + int result = 0; + tinfl_decompressor decomp; + mz_uint8 *pDict = (mz_uint8 *)MZ_MALLOC(TINFL_LZ_DICT_SIZE); + size_t in_buf_ofs = 0, dict_ofs = 0; + if (!pDict) + return TINFL_STATUS_FAILED; + tinfl_init(&decomp); + for (;;) + { + size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs; + tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size, + (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); + in_buf_ofs += in_buf_size; + if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user))) + break; + if (status != TINFL_STATUS_HAS_MORE_OUTPUT) + { + result = (status == TINFL_STATUS_DONE); + break; + } + dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1); + } + MZ_FREE(pDict); + *pIn_buf_size = in_buf_ofs; + return result; +} + +tinfl_decompressor *tinfl_decompressor_alloc() +{ + tinfl_decompressor *pDecomp = (tinfl_decompressor *)MZ_MALLOC(sizeof(tinfl_decompressor)); + if (pDecomp) + tinfl_init(pDecomp); + return pDecomp; +} + +void tinfl_decompressor_free(tinfl_decompressor *pDecomp) +{ + MZ_FREE(pDecomp); +} + +#ifdef __cplusplus +} +#endif +/************************************************************************** + * + * Copyright 2013-2014 RAD Game Tools and Valve Software + * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC + * Copyright 2016 Martin Raiber + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------- .ZIP archive reading */ + +#ifdef MINIZ_NO_STDIO +#define MZ_FILE void * +#else +#include + +#if defined(_MSC_VER) || defined(__MINGW64__) +static FILE *mz_fopen(const char *pFilename, const char *pMode) +{ + FILE *pFile = NULL; + fopen_s(&pFile, pFilename, pMode); + return pFile; +} +static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) +{ + FILE *pFile = NULL; + if (freopen_s(&pFile, pPath, pMode, pStream)) + return NULL; + return pFile; +} +#ifndef MINIZ_NO_TIME +#include +#endif +#define MZ_FOPEN mz_fopen +#define MZ_FCLOSE fclose +#define MZ_FREAD fread +#define MZ_FWRITE fwrite +#define MZ_FTELL64 _ftelli64 +#define MZ_FSEEK64 _fseeki64 +#define MZ_FILE_STAT_STRUCT _stat +#define MZ_FILE_STAT _stat +#define MZ_FFLUSH fflush +#define MZ_FREOPEN mz_freopen +#define MZ_DELETE_FILE remove +#elif defined(__MINGW32__) +#ifndef MINIZ_NO_TIME +#include +#endif +#define MZ_FOPEN(f, m) fopen(f, m) +#define MZ_FCLOSE fclose +#define MZ_FREAD fread +#define MZ_FWRITE fwrite +#define MZ_FTELL64 ftello64 +#define MZ_FSEEK64 fseeko64 +#define MZ_FILE_STAT_STRUCT _stat +#define MZ_FILE_STAT _stat +#define MZ_FFLUSH fflush +#define MZ_FREOPEN(f, m, s) freopen(f, m, s) +#define MZ_DELETE_FILE remove +#elif defined(__TINYC__) +#ifndef MINIZ_NO_TIME +#include +#endif +#define MZ_FOPEN(f, m) fopen(f, m) +#define MZ_FCLOSE fclose +#define MZ_FREAD fread +#define MZ_FWRITE fwrite +#define MZ_FTELL64 ftell +#define MZ_FSEEK64 fseek +#define MZ_FILE_STAT_STRUCT stat +#define MZ_FILE_STAT stat +#define MZ_FFLUSH fflush +#define MZ_FREOPEN(f, m, s) freopen(f, m, s) +#define MZ_DELETE_FILE remove +#elif defined(__GNUC__) && _LARGEFILE64_SOURCE +#ifndef MINIZ_NO_TIME +#include +#endif +#define MZ_FOPEN(f, m) fopen64(f, m) +#define MZ_FCLOSE fclose +#define MZ_FREAD fread +#define MZ_FWRITE fwrite +#define MZ_FTELL64 ftello64 +#define MZ_FSEEK64 fseeko64 +#define MZ_FILE_STAT_STRUCT stat64 +#define MZ_FILE_STAT stat64 +#define MZ_FFLUSH fflush +#define MZ_FREOPEN(p, m, s) freopen64(p, m, s) +#define MZ_DELETE_FILE remove +#elif defined(__APPLE__) && _LARGEFILE64_SOURCE +#ifndef MINIZ_NO_TIME +#include +#endif +#define MZ_FOPEN(f, m) fopen(f, m) +#define MZ_FCLOSE fclose +#define MZ_FREAD fread +#define MZ_FWRITE fwrite +#define MZ_FTELL64 ftello +#define MZ_FSEEK64 fseeko +#define MZ_FILE_STAT_STRUCT stat +#define MZ_FILE_STAT stat +#define MZ_FFLUSH fflush +#define MZ_FREOPEN(p, m, s) freopen(p, m, s) +#define MZ_DELETE_FILE remove + +#else +#pragma message("Using fopen, ftello, fseeko, stat() etc. path for file I/O - this path may not support large files.") +#ifndef MINIZ_NO_TIME +#include +#endif +#define MZ_FOPEN(f, m) fopen(f, m) +#define MZ_FCLOSE fclose +#define MZ_FREAD fread +#define MZ_FWRITE fwrite +#define MZ_FTELL64 ftello +#define MZ_FSEEK64 fseeko +#define MZ_FILE_STAT_STRUCT stat +#define MZ_FILE_STAT stat +#define MZ_FFLUSH fflush +#define MZ_FREOPEN(f, m, s) freopen(f, m, s) +#define MZ_DELETE_FILE remove +#endif /* #ifdef _MSC_VER */ +#endif /* #ifdef MINIZ_NO_STDIO */ + +#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c)) + +/* Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff. */ +enum +{ + /* ZIP archive identifiers and record sizes */ + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, + MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, + MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50, + MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22, + + /* ZIP64 archive identifier and record sizes */ + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50, + MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50, + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56, + MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20, + MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001, + MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50, + MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24, + MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16, + + /* Central directory header record offsets */ + MZ_ZIP_CDH_SIG_OFS = 0, + MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, + MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, + MZ_ZIP_CDH_BIT_FLAG_OFS = 8, + MZ_ZIP_CDH_METHOD_OFS = 10, + MZ_ZIP_CDH_FILE_TIME_OFS = 12, + MZ_ZIP_CDH_FILE_DATE_OFS = 14, + MZ_ZIP_CDH_CRC32_OFS = 16, + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, + MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, + MZ_ZIP_CDH_EXTRA_LEN_OFS = 30, + MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, + MZ_ZIP_CDH_DISK_START_OFS = 34, + MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, + MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42, + + /* Local directory header offsets */ + MZ_ZIP_LDH_SIG_OFS = 0, + MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, + MZ_ZIP_LDH_BIT_FLAG_OFS = 6, + MZ_ZIP_LDH_METHOD_OFS = 8, + MZ_ZIP_LDH_FILE_TIME_OFS = 10, + MZ_ZIP_LDH_FILE_DATE_OFS = 12, + MZ_ZIP_LDH_CRC32_OFS = 14, + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22, + MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, + MZ_ZIP_LDH_EXTRA_LEN_OFS = 28, + MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR = 1 << 3, + + /* End of central directory offsets */ + MZ_ZIP_ECDH_SIG_OFS = 0, + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8, + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, + MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, + MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, + MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20, + + /* ZIP64 End of central directory locator offsets */ + MZ_ZIP64_ECDL_SIG_OFS = 0, /* 4 bytes */ + MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4, /* 4 bytes */ + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8, /* 8 bytes */ + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */ + + /* ZIP64 End of central directory header offsets */ + MZ_ZIP64_ECDH_SIG_OFS = 0, /* 4 bytes */ + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4, /* 8 bytes */ + MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12, /* 2 bytes */ + MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14, /* 2 bytes */ + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16, /* 4 bytes */ + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20, /* 4 bytes */ + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */ + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32, /* 8 bytes */ + MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40, /* 8 bytes */ + MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48, /* 8 bytes */ + MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0, + MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10, + MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1, + MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32, + MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64, + MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192, + MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11 +}; + +typedef struct +{ + void *m_p; + size_t m_size, m_capacity; + mz_uint m_element_size; +} mz_zip_array; + +struct mz_zip_internal_state_tag +{ + mz_zip_array m_central_dir; + mz_zip_array m_central_dir_offsets; + mz_zip_array m_sorted_central_dir_offsets; + + /* The flags passed in when the archive is initially opened. */ + uint32_t m_init_flags; + + /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc. */ + mz_bool m_zip64; + + /* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64 will also be slammed to true too, even if we didn't find a zip64 end of central dir header, etc.) */ + mz_bool m_zip64_has_extended_info_fields; + + /* These fields are used by the file, FILE, memory, and memory/heap read/write helpers. */ + MZ_FILE *m_pFile; + mz_uint64 m_file_archive_start_ofs; + + void *m_pMem; + size_t m_mem_size; + size_t m_mem_capacity; +}; + +#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size + +#if defined(DEBUG) || defined(_DEBUG) || defined(NDEBUG) +static MZ_FORCEINLINE mz_uint mz_zip_array_range_check(const mz_zip_array *pArray, mz_uint index) +{ + MZ_ASSERT(index < pArray->m_size); + return index; +} +#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[mz_zip_array_range_check(array_ptr, index)] +#else +#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index] +#endif + +static MZ_FORCEINLINE void mz_zip_array_init(mz_zip_array *pArray, mz_uint32 element_size) +{ + memset(pArray, 0, sizeof(mz_zip_array)); + pArray->m_element_size = element_size; +} + +static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray) +{ + pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p); + memset(pArray, 0, sizeof(mz_zip_array)); +} + +static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing) +{ + void *pNew_p; + size_t new_capacity = min_new_capacity; + MZ_ASSERT(pArray->m_element_size); + if (pArray->m_capacity >= min_new_capacity) + return MZ_TRUE; + if (growing) + { + new_capacity = MZ_MAX(1, pArray->m_capacity); + while (new_capacity < min_new_capacity) + new_capacity *= 2; + } + if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) + return MZ_FALSE; + pArray->m_p = pNew_p; + pArray->m_capacity = new_capacity; + return MZ_TRUE; +} + +static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing) +{ + if (new_capacity > pArray->m_capacity) + { + if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) + return MZ_FALSE; + } + return MZ_TRUE; +} + +static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing) +{ + if (new_size > pArray->m_capacity) + { + if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) + return MZ_FALSE; + } + pArray->m_size = new_size; + return MZ_TRUE; +} + +static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n) +{ + return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE); +} + +static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n) +{ + size_t orig_size = pArray->m_size; + if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) + return MZ_FALSE; + memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size); + return MZ_TRUE; +} + +#ifndef MINIZ_NO_TIME +static MZ_TIME_T mz_zip_dos_to_time_t(int dos_time, int dos_date) +{ + struct tm tm; + memset(&tm, 0, sizeof(tm)); + tm.tm_isdst = -1; + tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; + tm.tm_mon = ((dos_date >> 5) & 15) - 1; + tm.tm_mday = dos_date & 31; + tm.tm_hour = (dos_time >> 11) & 31; + tm.tm_min = (dos_time >> 5) & 63; + tm.tm_sec = (dos_time << 1) & 62; + return mktime(&tm); +} + +static void mz_zip_time_t_to_dos_time(MZ_TIME_T time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date) +{ +#ifdef _MSC_VER + struct tm tm_struct; + struct tm *tm = &tm_struct; + errno_t err = localtime_s(tm, &time); + if (err) + { + *pDOS_date = 0; + *pDOS_time = 0; + return; + } +#else + struct tm *tm = localtime(&time); +#endif /* #ifdef _MSC_VER */ + + *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1)); + *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday); +} + +#ifndef MINIZ_NO_STDIO +static mz_bool mz_zip_get_file_modified_time(const char *pFilename, MZ_TIME_T *pTime) +{ + struct MZ_FILE_STAT_STRUCT file_stat; + + /* On Linux with x86 glibc, this call will fail on large files (I think >= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. */ + if (MZ_FILE_STAT(pFilename, &file_stat) != 0) + return MZ_FALSE; + + *pTime = file_stat.st_mtime; + + return MZ_TRUE; +} + +static mz_bool mz_zip_set_file_times(const char *pFilename, MZ_TIME_T access_time, MZ_TIME_T modified_time) +{ + struct utimbuf t; + + memset(&t, 0, sizeof(t)); + t.actime = access_time; + t.modtime = modified_time; + + return !utime(pFilename, &t); +} +#endif /* #ifndef MINIZ_NO_STDIO */ +#endif /* #ifndef MINIZ_NO_TIME */ + +static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, mz_zip_error err_num) +{ + if (pZip) + pZip->m_last_error = err_num; + return MZ_FALSE; +} + +static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint flags) +{ + (void)flags; + if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (!pZip->m_pAlloc) + pZip->m_pAlloc = miniz_def_alloc_func; + if (!pZip->m_pFree) + pZip->m_pFree = miniz_def_free_func; + if (!pZip->m_pRealloc) + pZip->m_pRealloc = miniz_def_realloc_func; + + pZip->m_archive_size = 0; + pZip->m_central_directory_file_ofs = 0; + pZip->m_total_files = 0; + pZip->m_last_error = MZ_ZIP_NO_ERROR; + + if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); + pZip->m_pState->m_init_flags = flags; + pZip->m_pState->m_zip64 = MZ_FALSE; + pZip->m_pState->m_zip64_has_extended_info_fields = MZ_FALSE; + + pZip->m_zip_mode = MZ_ZIP_MODE_READING; + + return MZ_TRUE; +} + +static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index) +{ + const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; + const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index)); + mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS); + mz_uint8 l = 0, r = 0; + pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + pE = pL + MZ_MIN(l_len, r_len); + while (pL < pE) + { + if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) + break; + pL++; + pR++; + } + return (pL == pE) ? (l_len < r_len) : (l < r); +} + +#define MZ_SWAP_UINT32(a, b) \ + do \ + { \ + mz_uint32 t = a; \ + a = b; \ + b = t; \ + } \ + MZ_MACRO_END + +/* Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.) */ +static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) +{ + mz_zip_internal_state *pState = pZip->m_pState; + const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets; + const mz_zip_array *pCentral_dir = &pState->m_central_dir; + mz_uint32 *pIndices; + mz_uint32 start, end; + const mz_uint32 size = pZip->m_total_files; + + if (size <= 1U) + return; + + pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); + + start = (size - 2U) >> 1U; + for (;;) + { + mz_uint64 child, root = start; + for (;;) + { + if ((child = (root << 1U) + 1U) >= size) + break; + child += (((child + 1U) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U]))); + if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) + break; + MZ_SWAP_UINT32(pIndices[root], pIndices[child]); + root = child; + } + if (!start) + break; + start--; + } + + end = size - 1; + while (end > 0) + { + mz_uint64 child, root = 0; + MZ_SWAP_UINT32(pIndices[end], pIndices[0]); + for (;;) + { + if ((child = (root << 1U) + 1U) >= end) + break; + child += (((child + 1U) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U])); + if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) + break; + MZ_SWAP_UINT32(pIndices[root], pIndices[child]); + root = child; + } + end--; + } +} + +static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip, mz_uint32 record_sig, mz_uint32 record_size, mz_int64 *pOfs) +{ + mz_int64 cur_file_ofs; + mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; + mz_uint8 *pBuf = (mz_uint8 *)buf_u32; + + /* Basic sanity checks - reject files which are too small */ + if (pZip->m_archive_size < record_size) + return MZ_FALSE; + + /* Find the record by scanning the file from the end towards the beginning. */ + cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0); + for (;;) + { + int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs); + + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n) + return MZ_FALSE; + + for (i = n - 4; i >= 0; --i) + { + mz_uint s = MZ_READ_LE32(pBuf + i); + if (s == record_sig) + { + if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size) + break; + } + } + + if (i >= 0) + { + cur_file_ofs += i; + break; + } + + /* Give up if we've searched the entire file, or we've gone back "too far" (~64kb) */ + if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (MZ_UINT16_MAX + record_size))) + return MZ_FALSE; + + cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0); + } + + *pOfs = cur_file_ofs; + return MZ_TRUE; +} + +static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flags) +{ + mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0, cdir_disk_index = 0; + mz_uint64 cdir_ofs = 0; + mz_int64 cur_file_ofs = 0; + const mz_uint8 *p; + + mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; + mz_uint8 *pBuf = (mz_uint8 *)buf_u32; + mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0); + mz_uint32 zip64_end_of_central_dir_locator_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32; + + mz_uint32 zip64_end_of_central_dir_header_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8 *pZip64_end_of_central_dir = (mz_uint8 *)zip64_end_of_central_dir_header_u32; + + mz_uint64 zip64_end_of_central_dir_ofs = 0; + + /* Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. */ + if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); + + if (!mz_zip_reader_locate_header_sig(pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs)) + return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR); + + /* Read and verify the end of central directory record. */ + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + + if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) + return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); + + if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) + { + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE, pZip64_locator, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) + { + if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG) + { + zip64_end_of_central_dir_ofs = MZ_READ_LE64(pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS); + if (zip64_end_of_central_dir_ofs > (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) + return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); + + if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs, pZip64_end_of_central_dir, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) + { + if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG) + { + pZip->m_pState->m_zip64 = MZ_TRUE; + } + } + } + } + } + + pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS); + cdir_entries_on_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS); + num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS); + cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS); + cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS); + cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); + + if (pZip->m_pState->m_zip64) + { + mz_uint32 zip64_total_num_of_disks = MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS); + mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS); + mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS); + mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS); + mz_uint64 zip64_size_of_central_directory = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS); + + if (zip64_size_of_end_of_central_dir_record < (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + if (zip64_total_num_of_disks != 1U) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); + + /* Check for miniz's practical limits */ + if (zip64_cdir_total_entries > MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + + pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries; + + if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + + cdir_entries_on_this_disk = (mz_uint32)zip64_cdir_total_entries_on_this_disk; + + /* Check for miniz's current practical limits (sorry, this should be enough for millions of files) */ + if (zip64_size_of_central_directory > MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); + + cdir_size = (mz_uint32)zip64_size_of_central_directory; + + num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS); + + cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS); + + cdir_ofs = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS); + } + + if (pZip->m_total_files != cdir_entries_on_this_disk) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); + + if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1))) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); + + if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + pZip->m_central_directory_file_ofs = cdir_ofs; + + if (pZip->m_total_files) + { + mz_uint i, n; + /* Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and possibly another to hold the sorted indices. */ + if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) || + (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE))) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + if (sort_central_dir) + { + if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE)) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + + /* Now create an index into the central directory file records, do some basic sanity checking on each record */ + p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p; + for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) + { + mz_uint total_header_size, disk_index, bit_flags, filename_size, ext_data_size; + mz_uint64 comp_size, decomp_size, local_header_ofs; + + if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p); + + if (sort_central_dir) + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i; + + comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); + local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS); + filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS); + + if ((!pZip->m_pState->m_zip64_has_extended_info_fields) && + (ext_data_size) && + (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == MZ_UINT32_MAX)) + { + /* Attempt to find zip64 extended information field in the entry's extra data */ + mz_uint32 extra_size_remaining = ext_data_size; + + if (extra_size_remaining) + { + const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size; + + do + { + if (extra_size_remaining < (sizeof(mz_uint16) * 2)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + mz_uint32 field_id = MZ_READ_LE16(pExtra_data); + mz_uint32 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); + + if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) + { + /* Ok, the archive didn't have any zip64 headers but it uses a zip64 extended information field so mark it as zip64 anyway (this can occur with infozip's zip util when it reads compresses files from stdin). */ + pZip->m_pState->m_zip64 = MZ_TRUE; + pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE; + break; + } + + pExtra_data += sizeof(mz_uint16) * 2 + field_data_size; + extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size; + } while (extra_size_remaining); + } + } + + /* I've seen archives that aren't marked as zip64 that uses zip64 ext data, argh */ + if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX)) + { + if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } + + disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS); + if ((disk_index == MZ_UINT16_MAX) || ((disk_index != num_this_disk) && (disk_index != 1))) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); + + if (comp_size != MZ_UINT32_MAX) + { + if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } + + bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); + if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); + + if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + n -= total_header_size; + p += total_header_size; + } + } + + if (sort_central_dir) + mz_zip_reader_sort_central_dir_offsets_by_filename(pZip); + + return MZ_TRUE; +} + +void mz_zip_zero_struct(mz_zip_archive *pZip) +{ + if (pZip) + MZ_CLEAR_OBJ(*pZip); +} + +static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, mz_bool set_last_error) +{ + mz_bool status = MZ_TRUE; + + if (!pZip) + return MZ_FALSE; + + if ((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) + { + if (set_last_error) + pZip->m_last_error = MZ_ZIP_INVALID_PARAMETER; + + return MZ_FALSE; + } + + if (pZip->m_pState) + { + mz_zip_internal_state *pState = pZip->m_pState; + pZip->m_pState = NULL; + + mz_zip_array_clear(pZip, &pState->m_central_dir); + mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); + mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); + +#ifndef MINIZ_NO_STDIO + if (pState->m_pFile) + { + if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE) + { + if (MZ_FCLOSE(pState->m_pFile) == EOF) + { + if (set_last_error) + pZip->m_last_error = MZ_ZIP_FILE_CLOSE_FAILED; + status = MZ_FALSE; + } + } + pState->m_pFile = NULL; + } +#endif /* #ifndef MINIZ_NO_STDIO */ + + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + } + pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; + + return status; +} + +mz_bool mz_zip_reader_end(mz_zip_archive *pZip) +{ + return mz_zip_reader_end_internal(pZip, MZ_TRUE); +} +mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags) +{ + if ((!pZip) || (!pZip->m_pRead)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (!mz_zip_reader_init_internal(pZip, flags)) + return MZ_FALSE; + + pZip->m_zip_type = MZ_ZIP_TYPE_USER; + pZip->m_archive_size = size; + + if (!mz_zip_reader_read_central_dir(pZip, flags)) + { + mz_zip_reader_end_internal(pZip, MZ_FALSE); + return MZ_FALSE; + } + + return MZ_TRUE; +} + +static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) +{ + mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; + size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n); + memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s); + return s; +} + +mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags) +{ + if (!pMem) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); + + if (!mz_zip_reader_init_internal(pZip, flags)) + return MZ_FALSE; + + pZip->m_zip_type = MZ_ZIP_TYPE_MEMORY; + pZip->m_archive_size = size; + pZip->m_pRead = mz_zip_mem_read_func; + pZip->m_pIO_opaque = pZip; + +#ifdef __cplusplus + pZip->m_pState->m_pMem = const_cast(pMem); +#else + pZip->m_pState->m_pMem = (void *)pMem; +#endif + + pZip->m_pState->m_mem_size = size; + + if (!mz_zip_reader_read_central_dir(pZip, flags)) + { + mz_zip_reader_end_internal(pZip, MZ_FALSE); + return MZ_FALSE; + } + + return MZ_TRUE; +} + +#ifndef MINIZ_NO_STDIO +static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) +{ + mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; + mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); + + file_ofs += pZip->m_pState->m_file_archive_start_ofs; + + if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) + return 0; + + return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile); +} + +mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags) +{ + return mz_zip_reader_init_file_v2(pZip, pFilename, flags, 0, 0); +} + +mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags, mz_uint64 file_start_ofs, mz_uint64 archive_size) +{ + if ((!pZip) || (!pFilename) || ((archive_size) && (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE))) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + mz_uint64 file_size; + MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb"); + if (!pFile) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); + + file_size = archive_size; + if (!file_size) + { + if (MZ_FSEEK64(pFile, 0, SEEK_END)) + { + MZ_FCLOSE(pFile); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED); + } + + file_size = MZ_FTELL64(pFile); + } + + /* TODO: Better sanity check archive_size and the # of actual remaining bytes */ + + if (file_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); + + if (!mz_zip_reader_init_internal(pZip, flags)) + { + MZ_FCLOSE(pFile); + return MZ_FALSE; + } + + pZip->m_zip_type = MZ_ZIP_TYPE_FILE; + pZip->m_pRead = mz_zip_file_read_func; + pZip->m_pIO_opaque = pZip; + pZip->m_pState->m_pFile = pFile; + pZip->m_archive_size = file_size; + pZip->m_pState->m_file_archive_start_ofs = file_start_ofs; + + if (!mz_zip_reader_read_central_dir(pZip, flags)) + { + mz_zip_reader_end_internal(pZip, MZ_FALSE); + return MZ_FALSE; + } + + return MZ_TRUE; +} + +mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 archive_size, mz_uint flags) +{ + mz_uint64 cur_file_ofs; + + if ((!pZip) || (!pFile)) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); + + cur_file_ofs = MZ_FTELL64(pFile); + + if (!archive_size) + { + if (MZ_FSEEK64(pFile, 0, SEEK_END)) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED); + + archive_size = MZ_FTELL64(pFile) - cur_file_ofs; + + if (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); + } + + if (!mz_zip_reader_init_internal(pZip, flags)) + return MZ_FALSE; + + pZip->m_zip_type = MZ_ZIP_TYPE_CFILE; + pZip->m_pRead = mz_zip_file_read_func; + + pZip->m_pIO_opaque = pZip; + pZip->m_pState->m_pFile = pFile; + pZip->m_archive_size = archive_size; + pZip->m_pState->m_file_archive_start_ofs = cur_file_ofs; + + if (!mz_zip_reader_read_central_dir(pZip, flags)) + { + mz_zip_reader_end_internal(pZip, MZ_FALSE); + return MZ_FALSE; + } + + return MZ_TRUE; +} + +#endif /* #ifndef MINIZ_NO_STDIO */ + +static MZ_FORCEINLINE const mz_uint8 *mz_zip_get_cdh(mz_zip_archive *pZip, mz_uint file_index) +{ + if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files)) + return NULL; + return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); +} + +mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index) +{ + mz_uint m_bit_flag; + const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index); + if (!p) + { + mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + return MZ_FALSE; + } + + m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); + return (m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) != 0; +} + +mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index) +{ + mz_uint bit_flag; + mz_uint method; + + const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index); + if (!p) + { + mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + return MZ_FALSE; + } + + method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS); + bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); + + if ((method != 0) && (method != MZ_DEFLATED)) + { + mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD); + return MZ_FALSE; + } + + if (bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) + { + mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); + return MZ_FALSE; + } + + if (bit_flag & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG) + { + mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE); + return MZ_FALSE; + } + + return MZ_TRUE; +} + +mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index) +{ + mz_uint filename_len, attribute_mapping_id, external_attr; + const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index); + if (!p) + { + mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + return MZ_FALSE; + } + + filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + if (filename_len) + { + if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/') + return MZ_TRUE; + } + + /* Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. */ + /* Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field. */ + /* FIXME: Remove this check? Is it necessary - we already check the filename. */ + attribute_mapping_id = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS) >> 8; + (void)attribute_mapping_id; + + external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); + if ((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0) + { + return MZ_TRUE; + } + + return MZ_FALSE; +} + +static mz_bool mz_zip_file_stat_internal(mz_zip_archive *pZip, mz_uint file_index, const mz_uint8 *pCentral_dir_header, mz_zip_archive_file_stat *pStat, mz_bool *pFound_zip64_extra_data) +{ + mz_uint n; + const mz_uint8 *p = pCentral_dir_header; + + if (pFound_zip64_extra_data) + *pFound_zip64_extra_data = MZ_FALSE; + + if ((!p) || (!pStat)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + /* Extract fields from the central directory record. */ + pStat->m_file_index = file_index; + pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index); + pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS); + pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS); + pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); + pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS); +#ifndef MINIZ_NO_TIME + pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS)); +#endif + pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS); + pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); + pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS); + pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); + pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS); + + /* Copy as much of the filename and comment as possible. */ + n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1); + memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); + pStat->m_filename[n] = '\0'; + + n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); + n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1); + pStat->m_comment_size = n; + memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n); + pStat->m_comment[n] = '\0'; + + /* Set some flags for convienance */ + pStat->m_is_directory = mz_zip_reader_is_file_a_directory(pZip, file_index); + pStat->m_is_encrypted = mz_zip_reader_is_file_encrypted(pZip, file_index); + pStat->m_is_supported = mz_zip_reader_is_file_supported(pZip, file_index); + + /* See if we need to read any zip64 extended information fields. */ + /* Confusingly, these zip64 fields can be present even on non-zip64 archives (Debian zip on a huge files from stdin piped to stdout creates them). */ + if (MZ_MAX(MZ_MAX(pStat->m_comp_size, pStat->m_uncomp_size), pStat->m_local_header_ofs) == MZ_UINT32_MAX) + { + /* Attempt to find zip64 extended information field in the entry's extra data */ + mz_uint32 extra_size_remaining = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS); + + if (extra_size_remaining) + { + const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + + do + { + if (extra_size_remaining < (sizeof(mz_uint16) * 2)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + mz_uint32 field_id = MZ_READ_LE16(pExtra_data); + mz_uint32 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); + + if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) + { + const mz_uint8 *pField_data = pExtra_data + sizeof(mz_uint16) * 2; + mz_uint32 field_data_remaining = field_data_size; + + if (pFound_zip64_extra_data) + *pFound_zip64_extra_data = MZ_TRUE; + + if (pStat->m_uncomp_size == MZ_UINT32_MAX) + { + if (field_data_remaining < sizeof(mz_uint64)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + pStat->m_uncomp_size = MZ_READ_LE64(pField_data); + pField_data += sizeof(mz_uint64); + field_data_remaining -= sizeof(mz_uint64); + } + + if (pStat->m_comp_size == MZ_UINT32_MAX) + { + if (field_data_remaining < sizeof(mz_uint64)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + pStat->m_comp_size = MZ_READ_LE64(pField_data); + pField_data += sizeof(mz_uint64); + field_data_remaining -= sizeof(mz_uint64); + } + + if (pStat->m_local_header_ofs == MZ_UINT32_MAX) + { + if (field_data_remaining < sizeof(mz_uint64)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + pStat->m_local_header_ofs = MZ_READ_LE64(pField_data); + pField_data += sizeof(mz_uint64); + field_data_remaining -= sizeof(mz_uint64); + } + + break; + } + + pExtra_data += sizeof(mz_uint16) * 2 + field_data_size; + extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size; + } while (extra_size_remaining); + } + } + + return MZ_TRUE; +} + +static MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags) +{ + mz_uint i; + if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE) + return 0 == memcmp(pA, pB, len); + for (i = 0; i < len; ++i) + if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i])) + return MZ_FALSE; + return MZ_TRUE; +} + +static MZ_FORCEINLINE int mz_zip_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len) +{ + const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; + mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS); + mz_uint8 l = 0, r = 0; + pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + pE = pL + MZ_MIN(l_len, r_len); + while (pL < pE) + { + if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) + break; + pL++; + pR++; + } + return (pL == pE) ? (int)(l_len - r_len) : (l - r); +} + +static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename, mz_uint32 *pIndex) +{ + mz_zip_internal_state *pState = pZip->m_pState; + const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets; + const mz_zip_array *pCentral_dir = &pState->m_central_dir; + mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); + const uint32_t size = pZip->m_total_files; + const mz_uint filename_len = (mz_uint)strlen(pFilename); + + if (pIndex) + *pIndex = 0; + + if (size) + { + /* yes I could use uint32_t's, but then we would have to add some special case checks in the loop, argh, and */ + /* honestly the major expense here on 32-bit CPU's will still be the filename compare */ + mz_int64 l = 0, h = (mz_int64)size - 1; + + while (l <= h) + { + mz_int64 m = l + ((h - l) >> 1); + uint32_t file_index = pIndices[(uint32_t)m]; + + int comp = mz_zip_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len); + if (!comp) + { + if (pIndex) + *pIndex = file_index; + return MZ_TRUE; + } + else if (comp < 0) + l = m + 1; + else + h = m - 1; + } + } + + return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND); +} + +int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags) +{ + mz_uint32 index; + if (!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, &index)) + return -1; + else + return (int)index; +} + +mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *pIndex) +{ + mz_uint file_index; + size_t name_len, comment_len; + + if (pIndex) + *pIndex = 0; + + if ((!pZip) || (!pZip->m_pState) || (!pName)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + /* See if we can use a binary search */ + if (((pZip->m_pState->m_init_flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) && + (pZip->m_zip_mode == MZ_ZIP_MODE_READING) && + ((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size)) + { + return mz_zip_locate_file_binary_search(pZip, pName, pIndex); + } + + /* Locate the entry by scanning the entire central directory */ + name_len = strlen(pName); + if (name_len > MZ_UINT16_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + comment_len = pComment ? strlen(pComment) : 0; + if (comment_len > MZ_UINT16_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + for (file_index = 0; file_index < pZip->m_total_files; file_index++) + { + const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); + mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS); + const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + if (filename_len < name_len) + continue; + if (comment_len) + { + mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS); + const char *pFile_comment = pFilename + filename_len + file_extra_len; + if ((file_comment_len != comment_len) || (!mz_zip_string_equal(pComment, pFile_comment, file_comment_len, flags))) + continue; + } + if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) + { + int ofs = filename_len - 1; + do + { + if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':')) + break; + } while (--ofs >= 0); + ofs++; + pFilename += ofs; + filename_len -= ofs; + } + if ((filename_len == name_len) && (mz_zip_string_equal(pName, pFilename, filename_len, flags))) + { + if (pIndex) + *pIndex = file_index; + return MZ_TRUE; + } + } + + return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND); +} + +mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) +{ + int status = TINFL_STATUS_DONE; + mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail; + mz_zip_archive_file_stat file_stat; + void *pRead_buf; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; + tinfl_decompressor inflator; + + if ((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) || ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + return MZ_FALSE; + + /* A directory or zero length file */ + if ((file_stat.m_is_directory) || (!file_stat.m_comp_size)) + return MZ_TRUE; + + /* Encryption and patch files are not supported. */ + if (file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); + + /* This function only supports decompressing stored and deflate. */ + if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD); + + /* Ensure supplied output buffer is large enough. */ + needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size; + if (buf_size < needed_size) + return mz_zip_set_error(pZip, MZ_ZIP_BUF_TOO_SMALL); + + /* Read and parse the local directory entry. */ + cur_file_ofs = file_stat.m_local_header_ofs; + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) + { + /* The file is stored or the caller has requested the compressed data. */ + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + +#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS + if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0) + { + if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32) + return mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED); + } +#endif + + return MZ_TRUE; + } + + /* Decompress the file either directly from memory or from a file input buffer. */ + tinfl_init(&inflator); + + if (pZip->m_pState->m_pMem) + { + /* Read directly from the archive in memory. */ + pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; + read_buf_size = read_buf_avail = file_stat.m_comp_size; + comp_remaining = 0; + } + else if (pUser_read_buf) + { + /* Use a user provided read buffer. */ + if (!user_read_buf_size) + return MZ_FALSE; + pRead_buf = (mz_uint8 *)pUser_read_buf; + read_buf_size = user_read_buf_size; + read_buf_avail = 0; + comp_remaining = file_stat.m_comp_size; + } + else + { + /* Temporarily allocate a read buffer. */ + read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE); + if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) + return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + + if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + read_buf_avail = 0; + comp_remaining = file_stat.m_comp_size; + } + + do + { + /* The size_t cast here should be OK because we've verified that the output buffer is >= file_stat.m_uncomp_size above */ + size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs); + if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) + { + read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + status = TINFL_STATUS_FAILED; + mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED); + break; + } + cur_file_ofs += read_buf_avail; + comp_remaining -= read_buf_avail; + read_buf_ofs = 0; + } + in_buf_size = (size_t)read_buf_avail; + status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0)); + read_buf_avail -= in_buf_size; + read_buf_ofs += in_buf_size; + out_buf_ofs += out_buf_size; + } while (status == TINFL_STATUS_NEEDS_MORE_INPUT); + + if (status == TINFL_STATUS_DONE) + { + /* Make sure the entire file was decompressed, and check its CRC. */ + if (out_buf_ofs != file_stat.m_uncomp_size) + { + mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE); + status = TINFL_STATUS_FAILED; + } +#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS + else if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32) + { + mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED); + status = TINFL_STATUS_FAILED; + } +#endif + } + + if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf)) + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + + return status == TINFL_STATUS_DONE; +} + +mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) +{ + mz_uint32 file_index; + if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index)) + return MZ_FALSE; + return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size); +} + +mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags) +{ + return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0); +} + +mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags) +{ + return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0); +} + +void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags) +{ + mz_uint64 comp_size, uncomp_size, alloc_size; + const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index); + void *pBuf; + + if (pSize) + *pSize = 0; + + if (!p) + { + mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + return NULL; + } + + comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); + + alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size; + if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) + { + mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + return NULL; + } + + if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size))) + { + mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + return NULL; + } + + if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return NULL; + } + + if (pSize) + *pSize = (size_t)alloc_size; + return pBuf; +} + +void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags) +{ + mz_uint32 file_index; + if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index)) + { + if (pSize) + *pSize = 0; + return nullptr; + } + return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags); +} + +mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) +{ + int status = TINFL_STATUS_DONE; + mz_uint file_crc32 = MZ_CRC32_INIT; + mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs; + mz_zip_archive_file_stat file_stat; + void *pRead_buf = NULL; + void *pWrite_buf = NULL; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; + + if ((!pZip) || (!pZip->m_pState) || (!pCallback) || (!pZip->m_pRead)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + return MZ_FALSE; + + /* A directory or zero length file */ + if ((file_stat.m_is_directory) || (!file_stat.m_comp_size)) + return MZ_TRUE; + + /* Encryption and patch files are not supported. */ + if (file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); + + /* This function only supports decompressing stored and deflate. */ + if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD); + + /* Read and do some minimal validation of the local directory entry (this doesn't crack the zip64 stuff, which we already have from the central dir) */ + cur_file_ofs = file_stat.m_local_header_ofs; + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + /* Decompress the file either directly from memory or from a file input buffer. */ + if (pZip->m_pState->m_pMem) + { + pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; + read_buf_size = read_buf_avail = file_stat.m_comp_size; + comp_remaining = 0; + } + else + { + read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE); + if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + read_buf_avail = 0; + comp_remaining = file_stat.m_comp_size; + } + + if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) + { + /* The file is stored or the caller has requested the compressed data. */ + if (pZip->m_pState->m_pMem) + { + if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > MZ_UINT32_MAX)) + return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + + if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size) + { + mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED); + status = TINFL_STATUS_FAILED; + } + else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + { +#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS + file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size); +#endif + } + + cur_file_ofs += file_stat.m_comp_size; + out_buf_ofs += file_stat.m_comp_size; + comp_remaining = 0; + } + else + { + while (comp_remaining) + { + read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + status = TINFL_STATUS_FAILED; + break; + } + +#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS + if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + { + file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail); + } +#endif + + if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED); + status = TINFL_STATUS_FAILED; + break; + } + + cur_file_ofs += read_buf_avail; + out_buf_ofs += read_buf_avail; + comp_remaining -= read_buf_avail; + } + } + } + else + { + tinfl_decompressor inflator; + tinfl_init(&inflator); + + if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE))) + { + mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + status = TINFL_STATUS_FAILED; + } + else + { + do + { + mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); + size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); + if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) + { + read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + status = TINFL_STATUS_FAILED; + break; + } + cur_file_ofs += read_buf_avail; + comp_remaining -= read_buf_avail; + read_buf_ofs = 0; + } + + in_buf_size = (size_t)read_buf_avail; + status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0); + read_buf_avail -= in_buf_size; + read_buf_ofs += in_buf_size; + + if (out_buf_size) + { + if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size) + { + mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED); + status = TINFL_STATUS_FAILED; + break; + } + +#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS + file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size); +#endif + if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) + { + mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED); + status = TINFL_STATUS_FAILED; + break; + } + } + } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT)); + } + } + + if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) + { + /* Make sure the entire file was decompressed, and check its CRC. */ + if (out_buf_ofs != file_stat.m_uncomp_size) + { + mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE); + status = TINFL_STATUS_FAILED; + } +#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS + else if (file_crc32 != file_stat.m_crc32) + { + mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED); + status = TINFL_STATUS_FAILED; + } +#endif + } + + if (!pZip->m_pState->m_pMem) + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + + if (pWrite_buf) + pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf); + + return status == TINFL_STATUS_DONE; +} + +mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) +{ + mz_uint32 file_index; + if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index)) + return MZ_FALSE; + + return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags); +} + +#ifndef MINIZ_NO_STDIO +static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n) +{ + (void)ofs; + + return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque); +} + +mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags) +{ + mz_bool status; + mz_zip_archive_file_stat file_stat; + MZ_FILE *pFile; + + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + return MZ_FALSE; + + if ((file_stat.m_is_directory) || (!file_stat.m_is_supported)) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE); + + pFile = MZ_FOPEN(pDst_filename, "wb"); + if (!pFile) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); + + status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags); + + if (MZ_FCLOSE(pFile) == EOF) + { + if (status) + mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED); + + status = MZ_FALSE; + } + +#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO) + if (status) + mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time); +#endif + + return status; +} + +mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags) +{ + mz_uint32 file_index; + if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index)) + return MZ_FALSE; + + return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags); +} + +mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index, MZ_FILE *pFile, mz_uint flags) +{ + mz_zip_archive_file_stat file_stat; + + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + return MZ_FALSE; + + if ((file_stat.m_is_directory) || (!file_stat.m_is_supported)) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE); + + return mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags); +} + +mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags) +{ + mz_uint32 file_index; + if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index)) + return MZ_FALSE; + + return mz_zip_reader_extract_to_cfile(pZip, file_index, pFile, flags); +} +#endif /* #ifndef MINIZ_NO_STDIO */ + +static size_t mz_zip_compute_crc32_callback(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) +{ + mz_uint32 *p = (mz_uint32 *)pOpaque; + (void)file_ofs; + *p = (mz_uint32)mz_crc32(*p, (const mz_uint8 *)pBuf, n); + return n; +} + +mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags) +{ + mz_zip_archive_file_stat file_stat; + mz_zip_internal_state *pState; + const mz_uint8 *pCentral_dir_header; + mz_bool found_zip64_ext_data_in_cdir = MZ_FALSE; + mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; + mz_uint64 local_header_ofs = 0; + mz_uint32 local_header_filename_len, local_header_extra_len, local_header_crc32; + mz_uint64 local_header_comp_size, local_header_uncomp_size; + mz_uint32 uncomp_crc32 = MZ_CRC32_INIT; + mz_bool has_data_descriptor; + mz_uint32 local_header_bit_flags; + + mz_zip_array file_data_array; + mz_zip_array_init(&file_data_array, 1); + + if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (file_index > pZip->m_total_files) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + pState = pZip->m_pState; + + pCentral_dir_header = mz_zip_get_cdh(pZip, file_index); + + if (!mz_zip_file_stat_internal(pZip, file_index, pCentral_dir_header, &file_stat, &found_zip64_ext_data_in_cdir)) + return MZ_FALSE; + + /* A directory or zero length file */ + if ((file_stat.m_is_directory) || (!file_stat.m_uncomp_size)) + return MZ_TRUE; + + /* Encryption and patch files are not supported. */ + if (file_stat.m_is_encrypted) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); + + /* This function only supports stored and deflate. */ + if ((file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD); + + if (!file_stat.m_is_supported) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE); + + /* Read and parse the local directory entry. */ + local_header_ofs = file_stat.m_local_header_ofs; + if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + local_header_filename_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS); + local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS); + local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS); + local_header_crc32 = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_CRC32_OFS); + local_header_bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS); + has_data_descriptor = (local_header_bit_flags & 8) != 0; + + if (local_header_filename_len != strlen(file_stat.m_filename)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + if ((local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size) > pZip->m_archive_size) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + if (!mz_zip_array_resize(pZip, &file_data_array, MZ_MAX(local_header_filename_len, local_header_extra_len), MZ_FALSE)) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + if (local_header_filename_len) + { + if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE, file_data_array.m_p, local_header_filename_len) != local_header_filename_len) + { + mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + goto handle_failure; + } + + /* I've seen 1 archive that had the same pathname, but used backslashes in the local dir and forward slashes in the central dir. Do we care about this? For now, this case will fail validation. */ + if (memcmp(file_stat.m_filename, file_data_array.m_p, local_header_filename_len) != 0) + { + mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); + goto handle_failure; + } + } + + if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX))) + { + if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len, file_data_array.m_p, local_header_extra_len) != local_header_extra_len) + { + mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + goto handle_failure; + } + + mz_uint32 extra_size_remaining = local_header_extra_len; + const mz_uint8 *pExtra_data = (const mz_uint8 *)file_data_array.m_p; + + do + { + mz_uint32 field_id, field_data_size, field_total_size; + + if (extra_size_remaining < (sizeof(mz_uint16) * 2)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + field_id = MZ_READ_LE16(pExtra_data); + field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); + field_total_size = field_data_size + sizeof(mz_uint16) * 2; + + if (field_total_size > extra_size_remaining) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) + { + const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32); + + if (field_data_size < sizeof(mz_uint64) * 2) + { + mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + goto handle_failure; + } + + local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data); + local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64)); + + found_zip64_ext_data_in_ldir = MZ_TRUE; + break; + } + + pExtra_data += field_total_size; + extra_size_remaining -= field_total_size; + } while (extra_size_remaining); + } + + /* TODO: parse local header extra data when local_header_comp_size is 0xFFFFFFFF! (big_descriptor.zip) */ + /* I've seen zips in the wild with the data descriptor bit set, but proper local header values and bogus data descriptors */ + if ((has_data_descriptor) && (!local_header_comp_size) && (!local_header_crc32)) + { + mz_uint8 descriptor_buf[32]; + + mz_uint32 num_descriptor_uint32s = ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) ? 6 : 4; + + if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size, descriptor_buf, sizeof(mz_uint32) * num_descriptor_uint32s) != (sizeof(mz_uint32) * num_descriptor_uint32s)) + { + mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + goto handle_failure; + } + + mz_bool has_id = (MZ_READ_LE32(descriptor_buf) == MZ_ZIP_DATA_DESCRIPTOR_ID); + const mz_uint8 *pSrc = has_id ? (descriptor_buf + sizeof(mz_uint32)) : descriptor_buf; + + mz_uint32 file_crc32 = MZ_READ_LE32(pSrc); + mz_uint64 comp_size = 0, uncomp_size = 0; + + if ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) + { + comp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32)); + uncomp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32) + sizeof(mz_uint64)); + } + else + { + comp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32)); + uncomp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32) + sizeof(mz_uint32)); + } + + if ((file_crc32 != file_stat.m_crc32) || (comp_size != file_stat.m_comp_size) || (uncomp_size != file_stat.m_uncomp_size)) + { + mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); + goto handle_failure; + } + } + else + { + if ((local_header_crc32 != file_stat.m_crc32) || (local_header_comp_size != file_stat.m_comp_size) || (local_header_uncomp_size != file_stat.m_uncomp_size)) + { + mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); + goto handle_failure; + } + } + + mz_zip_array_clear(pZip, &file_data_array); + + if ((flags & MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY) == 0) + { + if (!mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_compute_crc32_callback, &uncomp_crc32, 0)) + return MZ_FALSE; + + /* 1 more check to be sure, although the extract checks too. */ + if (uncomp_crc32 != file_stat.m_crc32) + { + mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); + return MZ_FALSE; + } + } + + return MZ_TRUE; + +handle_failure: + mz_zip_array_clear(pZip, &file_data_array); + return MZ_FALSE; +} + +mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags) +{ + mz_zip_internal_state *pState; + uint32_t i; + + if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + pState = pZip->m_pState; + + /* Basic sanity checks */ + if (!pState->m_zip64) + { + if (pZip->m_total_files > MZ_UINT16_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + + if (pZip->m_archive_size > MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + } + else + { + if (pZip->m_total_files >= MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + + if (pState->m_central_dir.m_size >= MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + } + + for (i = 0; i < pZip->m_total_files; i++) + { + if (MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG & flags) + { + mz_uint32 found_index; + mz_zip_archive_file_stat stat; + + if (!mz_zip_reader_file_stat(pZip, i, &stat)) + return MZ_FALSE; + + if (!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, NULL, 0, &found_index)) + return MZ_FALSE; + + /* This check can fail if there are duplicate filenames in the archive (which we don't check for when writing - that's up to the user) */ + if (found_index != i) + return mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); + } + + if (!mz_zip_validate_file(pZip, i, flags)) + return MZ_FALSE; + } + + return MZ_TRUE; +} + +mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr) +{ + mz_bool success = MZ_TRUE; + mz_zip_archive zip; + mz_zip_error actual_err = MZ_ZIP_NO_ERROR; + + if ((!pMem) || (!size)) + { + if (pErr) + *pErr = MZ_ZIP_INVALID_PARAMETER; + return MZ_FALSE; + } + + mz_zip_zero_struct(&zip); + + if (!mz_zip_reader_init_mem(&zip, pMem, size, flags)) + { + if (pErr) + *pErr = zip.m_last_error; + return MZ_FALSE; + } + + if (!mz_zip_validate_archive(&zip, flags)) + { + actual_err = zip.m_last_error; + success = MZ_FALSE; + } + + if (!mz_zip_reader_end_internal(&zip, success)) + { + if (!actual_err) + actual_err = zip.m_last_error; + success = MZ_FALSE; + } + + if (pErr) + *pErr = actual_err; + + return success; +} + +#ifndef MINIZ_NO_STDIO +mz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zip_error *pErr) +{ + mz_bool success = MZ_TRUE; + mz_zip_archive zip; + mz_zip_error actual_err = MZ_ZIP_NO_ERROR; + + if (!pFilename) + { + if (pErr) + *pErr = MZ_ZIP_INVALID_PARAMETER; + return MZ_FALSE; + } + + mz_zip_zero_struct(&zip); + + if (!mz_zip_reader_init_file_v2(&zip, pFilename, flags, 0, 0)) + { + if (pErr) + *pErr = zip.m_last_error; + return MZ_FALSE; + } + + if (!mz_zip_validate_archive(&zip, flags)) + { + actual_err = zip.m_last_error; + success = MZ_FALSE; + } + + if (!mz_zip_reader_end_internal(&zip, success)) + { + if (!actual_err) + actual_err = zip.m_last_error; + success = MZ_FALSE; + } + + if (pErr) + *pErr = actual_err; + + return success; +} +#endif /* #ifndef MINIZ_NO_STDIO */ + +/* ------------------- .ZIP archive writing */ + +#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS + +static MZ_FORCEINLINE void mz_write_le16(mz_uint8 *p, mz_uint16 v) +{ + p[0] = (mz_uint8)v; + p[1] = (mz_uint8)(v >> 8); +} +static MZ_FORCEINLINE void mz_write_le32(mz_uint8 *p, mz_uint32 v) +{ + p[0] = (mz_uint8)v; + p[1] = (mz_uint8)(v >> 8); + p[2] = (mz_uint8)(v >> 16); + p[3] = (mz_uint8)(v >> 24); +} +static MZ_FORCEINLINE void mz_write_le64(mz_uint8 *p, mz_uint64 v) +{ + mz_write_le32(p, (mz_uint32)v); + mz_write_le32(p + sizeof(mz_uint32), (mz_uint32)(v >> 32)); +} + +#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v)) +#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v)) +#define MZ_WRITE_LE64(p, v) mz_write_le64((mz_uint8 *)(p), (mz_uint64)(v)) + +static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) +{ + mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; + mz_zip_internal_state *pState = pZip->m_pState; + mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size); + + if (!n) + return 0; + + /* An allocation this big is likely to just fail on 32-bit systems, so don't even go there. */ + if ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)) + { + mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE); + return 0; + } + + if (new_size > pState->m_mem_capacity) + { + void *pNew_block; + size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); + + while (new_capacity < new_size) + new_capacity *= 2; + + if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity))) + { + mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + return 0; + } + + pState->m_pMem = pNew_block; + pState->m_mem_capacity = new_capacity; + } + memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n); + pState->m_mem_size = (size_t)new_size; + return n; +} + +static mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip, mz_bool set_last_error) +{ + mz_zip_internal_state *pState; + mz_bool status = MZ_TRUE; + + if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))) + { + if (set_last_error) + mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + return MZ_FALSE; + } + + pState = pZip->m_pState; + pZip->m_pState = NULL; + mz_zip_array_clear(pZip, &pState->m_central_dir); + mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); + mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); + +#ifndef MINIZ_NO_STDIO + if (pState->m_pFile) + { + if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE) + { + if (MZ_FCLOSE(pState->m_pFile) == EOF) + { + if (set_last_error) + mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED); + status = MZ_FALSE; + } + } + + pState->m_pFile = NULL; + } +#endif /* #ifndef MINIZ_NO_STDIO */ + + if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem); + pState->m_pMem = NULL; + } + + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; + return status; +} + +mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_uint flags) +{ + mz_bool zip64 = (flags & MZ_ZIP_FLAG_WRITE_ZIP64) != 0; + + if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) + { + if (!pZip->m_pRead) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + } + + if (pZip->m_file_offset_alignment) + { + /* Ensure user specified file offset alignment is a power of 2. */ + if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + } + + if (!pZip->m_pAlloc) + pZip->m_pAlloc = miniz_def_alloc_func; + if (!pZip->m_pFree) + pZip->m_pFree = miniz_def_free_func; + if (!pZip->m_pRealloc) + pZip->m_pRealloc = miniz_def_realloc_func; + + pZip->m_archive_size = existing_size; + pZip->m_central_directory_file_ofs = 0; + pZip->m_total_files = 0; + + if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); + + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); + + pZip->m_pState->m_zip64 = zip64; + pZip->m_pState->m_zip64_has_extended_info_fields = zip64; + + pZip->m_zip_type = MZ_ZIP_TYPE_USER; + pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; + + return MZ_TRUE; +} + +mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size) +{ + return mz_zip_writer_init_v2(pZip, existing_size, 0); +} + +mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size, mz_uint flags) +{ + pZip->m_pWrite = mz_zip_heap_write_func; + + if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) + pZip->m_pRead = mz_zip_mem_read_func; + + pZip->m_pIO_opaque = pZip; + + if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags)) + return MZ_FALSE; + + pZip->m_zip_type = MZ_ZIP_TYPE_HEAP; + + if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning))) + { + if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size))) + { + mz_zip_writer_end_internal(pZip, MZ_FALSE); + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + pZip->m_pState->m_mem_capacity = initial_allocation_size; + } + + return MZ_TRUE; +} + +mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size) +{ + return mz_zip_writer_init_heap_v2(pZip, size_to_reserve_at_beginning, initial_allocation_size, 0); +} + +#ifndef MINIZ_NO_STDIO +static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) +{ + mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; + mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); + + file_ofs += pZip->m_pState->m_file_archive_start_ofs; + + if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) + { + mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED); + return 0; + } + + return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile); +} + +mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning) +{ + return mz_zip_writer_init_file_v2(pZip, pFilename, size_to_reserve_at_beginning, 0); +} + +mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning, mz_uint flags) +{ + MZ_FILE *pFile; + + pZip->m_pWrite = mz_zip_file_write_func; + + if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) + pZip->m_pRead = mz_zip_file_read_func; + + pZip->m_pIO_opaque = pZip; + + if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags)) + return MZ_FALSE; + + if (NULL == (pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) ? "w+b" : "wb"))) + { + mz_zip_writer_end(pZip); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); + } + + pZip->m_pState->m_pFile = pFile; + pZip->m_zip_type = MZ_ZIP_TYPE_FILE; + + if (size_to_reserve_at_beginning) + { + mz_uint64 cur_ofs = 0; + char buf[4096]; + + MZ_CLEAR_OBJ(buf); + + do + { + size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) + { + mz_zip_writer_end(pZip); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + cur_ofs += n; + size_to_reserve_at_beginning -= n; + } while (size_to_reserve_at_beginning); + } + + return MZ_TRUE; +} + +mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags) +{ + pZip->m_pWrite = mz_zip_file_write_func; + + if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) + pZip->m_pRead = mz_zip_file_read_func; + + pZip->m_pIO_opaque = pZip; + + if (!mz_zip_writer_init_v2(pZip, 0, flags)) + return MZ_FALSE; + + pZip->m_pState->m_pFile = pFile; + pZip->m_pState->m_file_archive_start_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); + pZip->m_zip_type = MZ_ZIP_TYPE_CFILE; + + return MZ_TRUE; +} +#endif /* #ifndef MINIZ_NO_STDIO */ + +mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags) +{ + mz_zip_internal_state *pState; + + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (flags & MZ_ZIP_FLAG_WRITE_ZIP64) + { + /* We don't support converting a non-zip64 file to zip64 - this seems like more trouble than it's worth. (What about the existing 32-bit data descriptors that could follow the compressed data?) */ + if (!pZip->m_pState->m_zip64) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + } + + /* No sense in trying to write to an archive that's already at the support max size */ + if (pZip->m_pState->m_zip64) + { + if (pZip->m_total_files == MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + } + else + { + if (pZip->m_total_files == MZ_UINT16_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + + if ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE); + } + + pState = pZip->m_pState; + + if (pState->m_pFile) + { +#ifdef MINIZ_NO_STDIO + (void)pFilename; + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); +#else + if (pZip->m_pIO_opaque != pZip) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE) + { + if (!pFilename) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + /* Archive is being read from stdio and was originally opened only for reading. Try to reopen as writable. */ + if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) + { + /* The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. */ + mz_zip_reader_end_internal(pZip, MZ_FALSE); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); + } + } + + pZip->m_pWrite = mz_zip_file_write_func; +#endif /* #ifdef MINIZ_NO_STDIO */ + } + else if (pState->m_pMem) + { + /* Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. */ + if (pZip->m_pIO_opaque != pZip) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + pState->m_mem_capacity = pState->m_mem_size; + pZip->m_pWrite = mz_zip_heap_write_func; + } + /* Archive is being read via a user provided read function - make sure the user has specified a write function too. */ + else if (!pZip->m_pWrite) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + /* Start writing new files at the archive's current central directory location. */ + /* TODO: We could add a flag that lets the user start writing immediately AFTER the existing central dir - this would be safer. */ + pZip->m_archive_size = pZip->m_central_directory_file_ofs; + pZip->m_central_directory_file_ofs = 0; + + /* Clear the sorted central dir offsets, they aren't useful or maintained now. */ + /* Even though we're now in write mode, files can still be extracted and verified, but file locates will be slow. */ + /* TODO: We could easily maintain the sorted central directory offsets. */ + mz_zip_array_clear(pZip, &pZip->m_pState->m_sorted_central_dir_offsets); + + pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; + + return MZ_TRUE; +} + +mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename) +{ + return mz_zip_writer_init_from_reader_v2(pZip, pFilename, 0); +} + +/* TODO: pArchive_name is a terrible name here! */ +mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags) +{ + return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0); +} + +typedef struct +{ + mz_zip_archive *m_pZip; + mz_uint64 m_cur_archive_file_ofs; + mz_uint64 m_comp_size; +} mz_zip_writer_add_state; + +static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len, void *pUser) +{ + mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser; + if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len) + return MZ_FALSE; + + pState->m_cur_archive_file_ofs += len; + pState->m_comp_size += len; + return MZ_TRUE; +} + +#define MZ_ZIP64_MAX_LOCAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 2) +#define MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 3) +static mz_uint32 mz_zip_writer_create_zip64_extra_data(mz_uint8 *pBuf, mz_uint64 *pUncomp_size, mz_uint64 *pComp_size, mz_uint64 *pLocal_header_ofs) +{ + mz_uint8 *pDst = pBuf; + + MZ_WRITE_LE16(pDst + 0, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID); + MZ_WRITE_LE16(pDst + 2, 0); + pDst += sizeof(mz_uint16) * 2; + + mz_uint32 field_size = 0; + + if (pUncomp_size) + { + MZ_WRITE_LE64(pDst, *pUncomp_size); + pDst += sizeof(mz_uint64); + field_size += sizeof(mz_uint64); + } + + if (pComp_size) + { + MZ_WRITE_LE64(pDst, *pComp_size); + pDst += sizeof(mz_uint64); + field_size += sizeof(mz_uint64); + } + + if (pLocal_header_ofs) + { + MZ_WRITE_LE64(pDst, *pLocal_header_ofs); + pDst += sizeof(mz_uint64); + field_size += sizeof(mz_uint64); + } + + MZ_WRITE_LE16(pBuf + 2, field_size); + + return (mz_uint32)(pDst - pBuf); +} + +static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date) +{ + (void)pZip; + memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX)); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX)); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size); + return MZ_TRUE; +} + +static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, + mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size, + mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, + mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, + mz_uint64 local_header_ofs, mz_uint32 ext_attributes) +{ + (void)pZip; + memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX)); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX)); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_MIN(local_header_ofs, MZ_UINT32_MAX)); + return MZ_TRUE; +} + +static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size, + const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size, + mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, + mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, + mz_uint64 local_header_ofs, mz_uint32 ext_attributes, + const char *user_extra_data, mz_uint user_extra_data_len) +{ + mz_zip_internal_state *pState = pZip->m_pState; + mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size; + size_t orig_central_dir_size = pState->m_central_dir.m_size; + mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; + + if (!pZip->m_pState->m_zip64) + { + if (local_header_ofs > 0xFFFFFFFF) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE); + } + + /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */ + if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + user_extra_data_len + comment_size) >= MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); + + if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size + user_extra_data_len, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes)) + return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + + if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir, user_extra_data, user_extra_data_len)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, ¢ral_dir_ofs, 1))) + { + /* Try to resize the central directory array back into its original state. */ + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + return MZ_TRUE; +} + +static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) +{ + /* Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. */ + if (*pArchive_name == '/') + return MZ_FALSE; + + while (*pArchive_name) + { + if ((*pArchive_name == '\\') || (*pArchive_name == ':')) + return MZ_FALSE; + + pArchive_name++; + } + + return MZ_TRUE; +} + +static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) +{ + mz_uint32 n; + if (!pZip->m_file_offset_alignment) + return 0; + n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1)); + return (mz_uint)((pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1)); +} + +static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n) +{ + char buf[4096]; + memset(buf, 0, MZ_MIN(sizeof(buf), n)); + while (n) + { + mz_uint32 s = MZ_MIN(sizeof(buf), n); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_file_ofs += s; + n -= s; + } + return MZ_TRUE; +} + +mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, + mz_uint64 uncomp_size, mz_uint32 uncomp_crc32) +{ + return mz_zip_writer_add_mem_ex_v2(pZip, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, uncomp_size, uncomp_crc32, NULL, NULL, 0, NULL, 0); +} + +mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, + mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified, + const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len) +{ + mz_uint16 method = 0, dos_time = 0, dos_date = 0; + mz_uint level, ext_attributes = 0, num_alignment_padding_bytes; + mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0; + size_t archive_name_size; + mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; + tdefl_compressor *pComp = NULL; + mz_bool store_data_uncompressed; + mz_zip_internal_state *pState; + mz_uint8 *pExtra_data = NULL; + mz_uint32 extra_size = 0; + mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE]; + mz_uint16 bit_flags = 0; + + if (uncomp_size || (buf_size && !(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) + bit_flags |= MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR; + + if (level_and_flags & MZ_ZIP_FLAG_UTF8_FILENAME) + bit_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8; + + if ((int)level_and_flags < 0) + level_and_flags = MZ_DEFAULT_LEVEL; + level = level_and_flags & 0xF; + store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)); + + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + pState = pZip->m_pState; + + if (pState->m_zip64) + { + if (pZip->m_total_files == MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + } + else + { + if (pZip->m_total_files == MZ_UINT16_MAX) + { + pState->m_zip64 = MZ_TRUE; + /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */ + } + if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF)) + { + pState->m_zip64 = MZ_TRUE; + /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ + } + } + + if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (!mz_zip_writer_validate_archive_name(pArchive_name)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME); + + if (last_modified != NULL) + { + mz_zip_time_t_to_dos_time(*last_modified, &dos_time, &dos_date); + } + else + { +#ifndef MINIZ_NO_TIME + { + MZ_TIME_T cur_time; + time(&cur_time); + mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date); + } +#endif /* #ifndef MINIZ_NO_TIME */ + } + + archive_name_size = strlen(pArchive_name); + if (archive_name_size > MZ_UINT16_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME); + + num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); + + /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */ + if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); + + if (!pState->m_zip64) + { + /* Bail early if the archive would obviously become too large */ + if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF) + { + pState->m_zip64 = MZ_TRUE; + /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ + } + } + + if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) + { + /* Set DOS Subdirectory attribute bit. */ + ext_attributes |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG; + + /* Subdirectories cannot contain data. */ + if ((buf_size) || (uncomp_size)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + } + + /* Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) */ + if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + (pState->m_zip64 ? MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE : 0))) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1))) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + if ((!store_data_uncompressed) && (buf_size)) + { + if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)))) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return MZ_FALSE; + } + + local_dir_header_ofs += num_alignment_padding_bytes; + if (pZip->m_file_offset_alignment) + { + MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); + } + cur_archive_file_ofs += num_alignment_padding_bytes; + + MZ_CLEAR_OBJ(local_dir_header); + + if (!store_data_uncompressed || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + { + method = MZ_DEFLATED; + } + + if (pState->m_zip64) + { + if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX) + { + pExtra_data = extra_data; + extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, + (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); + } + + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, extra_size + user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date)) + return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_archive_file_ofs += sizeof(local_dir_header); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + cur_archive_file_ofs += archive_name_size; + + if (pExtra_data != NULL) + { + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_archive_file_ofs += extra_size; + } + } + else + { + if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX)) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date)) + return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_archive_file_ofs += sizeof(local_dir_header); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + cur_archive_file_ofs += archive_name_size; + } + + if (user_extra_data_len > 0) + { + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_archive_file_ofs += user_extra_data_len; + } + + if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + { + uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size); + uncomp_size = buf_size; + if (uncomp_size <= 3) + { + level = 0; + store_data_uncompressed = MZ_TRUE; + } + } + + if (store_data_uncompressed) + { + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + + cur_archive_file_ofs += buf_size; + comp_size = buf_size; + } + else if (buf_size) + { + mz_zip_writer_add_state state; + + state.m_pZip = pZip; + state.m_cur_archive_file_ofs = cur_archive_file_ofs; + state.m_comp_size = 0; + + if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) || + (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED); + } + + comp_size = state.m_comp_size; + cur_archive_file_ofs = state.m_cur_archive_file_ofs; + } + + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + pComp = NULL; + + if (uncomp_size) + { + MZ_ASSERT(bit_flags & MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR); + + mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64]; + mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32; + + MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID); + MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32); + if (pExtra_data == NULL) + { + if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX)) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + + MZ_WRITE_LE32(local_dir_footer + 8, comp_size); + MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size); + } + else + { + MZ_WRITE_LE64(local_dir_footer + 8, comp_size); + MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size); + local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64; + } + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size) + return MZ_FALSE; + + cur_archive_file_ofs += local_dir_footer_size; + } + + if (pExtra_data != NULL) + { + extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, + (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); + } + + if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, extra_size, pComment, + comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes, + user_extra_data_central, user_extra_data_central_len)) + return MZ_FALSE; + + pZip->m_total_files++; + pZip->m_archive_size = cur_archive_file_ofs; + + return MZ_TRUE; +} + +#ifndef MINIZ_NO_STDIO +mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 size_to_add, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, + const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len) +{ + mz_uint16 gen_flags = MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR; + mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes; + mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0; + mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = size_to_add, comp_size = 0; + size_t archive_name_size; + mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; + mz_uint8 *pExtra_data = NULL; + mz_uint32 extra_size = 0; + mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE]; + mz_zip_internal_state *pState; + + if (level_and_flags & MZ_ZIP_FLAG_UTF8_FILENAME) + gen_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8; + + if ((int)level_and_flags < 0) + level_and_flags = MZ_DEFAULT_LEVEL; + level = level_and_flags & 0xF; + + /* Sanity checks */ + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + pState = pZip->m_pState; + + if ((!pState->m_zip64) && (uncomp_size > MZ_UINT32_MAX)) + { + /* Source file is too large for non-zip64 */ + /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ + pState->m_zip64 = MZ_TRUE; + } + + /* We could support this, but why? */ + if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (!mz_zip_writer_validate_archive_name(pArchive_name)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME); + + if (pState->m_zip64) + { + if (pZip->m_total_files == MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + } + else + { + if (pZip->m_total_files == MZ_UINT16_MAX) + { + pState->m_zip64 = MZ_TRUE; + /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */ + } + } + + archive_name_size = strlen(pArchive_name); + if (archive_name_size > MZ_UINT16_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME); + + num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); + + /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */ + if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); + + if (!pState->m_zip64) + { + /* Bail early if the archive would obviously become too large */ + if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024) > 0xFFFFFFFF) + { + pState->m_zip64 = MZ_TRUE; + /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ + } + } + +#ifndef MINIZ_NO_TIME + if (pFile_time) + { + mz_zip_time_t_to_dos_time(*pFile_time, &dos_time, &dos_date); + } +#endif + + if (uncomp_size <= 3) + level = 0; + + if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes)) + { + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + + cur_archive_file_ofs += num_alignment_padding_bytes; + local_dir_header_ofs = cur_archive_file_ofs; + + if (pZip->m_file_offset_alignment) + { + MZ_ASSERT((cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) == 0); + } + + if (uncomp_size && level) + { + method = MZ_DEFLATED; + } + + MZ_CLEAR_OBJ(local_dir_header); + if (pState->m_zip64) + { + if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX) + { + pExtra_data = extra_data; + extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, + (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); + } + + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, extra_size + user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date)) + return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_archive_file_ofs += sizeof(local_dir_header); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + { + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + + cur_archive_file_ofs += archive_name_size; + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_archive_file_ofs += extra_size; + } + else + { + if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX)) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date)) + return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_archive_file_ofs += sizeof(local_dir_header); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + { + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + + cur_archive_file_ofs += archive_name_size; + } + + if (user_extra_data_len > 0) + { + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_archive_file_ofs += user_extra_data_len; + } + + if (uncomp_size) + { + mz_uint64 uncomp_remaining = uncomp_size; + void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE); + if (!pRead_buf) + { + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + if (!level) + { + while (uncomp_remaining) + { + mz_uint n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining); + if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + } + uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n); + uncomp_remaining -= n; + cur_archive_file_ofs += n; + } + comp_size = uncomp_size; + } + else + { + mz_bool result = MZ_FALSE; + mz_zip_writer_add_state state; + tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)); + if (!pComp) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + state.m_pZip = pZip; + state.m_cur_archive_file_ofs = cur_archive_file_ofs; + state.m_comp_size = 0; + + if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + } + + for (;;) + { + size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE); + tdefl_status status; + + if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size) + { + mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + break; + } + + uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size); + uncomp_remaining -= in_buf_size; + + status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH); + if (status == TDEFL_STATUS_DONE) + { + result = MZ_TRUE; + break; + } + else if (status != TDEFL_STATUS_OKAY) + { + mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED); + break; + } + } + + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + + if (!result) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + return MZ_FALSE; + } + + comp_size = state.m_comp_size; + cur_archive_file_ofs = state.m_cur_archive_file_ofs; + } + + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + } + + mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64]; + mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32; + + MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID); + MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32); + if (pExtra_data == NULL) + { + if (comp_size > MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + + MZ_WRITE_LE32(local_dir_footer + 8, comp_size); + MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size); + } + else + { + MZ_WRITE_LE64(local_dir_footer + 8, comp_size); + MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size); + local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64; + } + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size) + return MZ_FALSE; + + cur_archive_file_ofs += local_dir_footer_size; + + if (pExtra_data != NULL) + { + extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, + (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); + } + + if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, extra_size, pComment, comment_size, + uncomp_size, comp_size, uncomp_crc32, method, gen_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes, + user_extra_data_central, user_extra_data_central_len)) + return MZ_FALSE; + + pZip->m_total_files++; + pZip->m_archive_size = cur_archive_file_ofs; + + return MZ_TRUE; +} + +mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) +{ + MZ_FILE *pSrc_file = NULL; + mz_uint64 uncomp_size = 0; + MZ_TIME_T file_modified_time; + MZ_TIME_T *pFile_time = NULL; + + memset(&file_modified_time, 0, sizeof(file_modified_time)); + +#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO) + pFile_time = &file_modified_time; + if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time)) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_STAT_FAILED); +#endif + + pSrc_file = MZ_FOPEN(pSrc_filename, "rb"); + if (!pSrc_file) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); + + MZ_FSEEK64(pSrc_file, 0, SEEK_END); + uncomp_size = MZ_FTELL64(pSrc_file); + MZ_FSEEK64(pSrc_file, 0, SEEK_SET); + + mz_bool status = mz_zip_writer_add_cfile(pZip, pArchive_name, pSrc_file, uncomp_size, pFile_time, pComment, comment_size, level_and_flags, NULL, 0, NULL, 0); + + MZ_FCLOSE(pSrc_file); + + return status; +} +#endif /* #ifndef MINIZ_NO_STDIO */ + +static mz_bool mz_zip_writer_update_zip64_extension_block(mz_zip_array *pNew_ext, mz_zip_archive *pZip, const mz_uint8 *pExt, uint32_t ext_len, mz_uint64 *pComp_size, mz_uint64 *pUncomp_size, mz_uint64 *pLocal_header_ofs, mz_uint32 *pDisk_start) +{ + /* + 64 should be enough for any new zip64 data */ + if (!mz_zip_array_reserve(pZip, pNew_ext, ext_len + 64, MZ_FALSE)) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + mz_zip_array_resize(pZip, pNew_ext, 0, MZ_FALSE); + + if ((pUncomp_size) || (pComp_size) || (pLocal_header_ofs) || (pDisk_start)) + { + mz_uint8 new_ext_block[64]; + mz_uint8 *pDst = new_ext_block; + mz_write_le16(pDst, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID); + mz_write_le16(pDst + sizeof(mz_uint16), 0); + pDst += sizeof(mz_uint16) * 2; + + if (pUncomp_size) + { + mz_write_le64(pDst, *pUncomp_size); + pDst += sizeof(mz_uint64); + } + + if (pComp_size) + { + mz_write_le64(pDst, *pComp_size); + pDst += sizeof(mz_uint64); + } + + if (pLocal_header_ofs) + { + mz_write_le64(pDst, *pLocal_header_ofs); + pDst += sizeof(mz_uint64); + } + + if (pDisk_start) + { + mz_write_le32(pDst, *pDisk_start); + pDst += sizeof(mz_uint32); + } + + mz_write_le16(new_ext_block + sizeof(mz_uint16), (mz_uint16)((pDst - new_ext_block) - sizeof(mz_uint16) * 2)); + + if (!mz_zip_array_push_back(pZip, pNew_ext, new_ext_block, pDst - new_ext_block)) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + if ((pExt) && (ext_len)) + { + mz_uint32 extra_size_remaining = ext_len; + const mz_uint8 *pExtra_data = pExt; + + do + { + mz_uint32 field_id, field_data_size, field_total_size; + + if (extra_size_remaining < (sizeof(mz_uint16) * 2)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + field_id = MZ_READ_LE16(pExtra_data); + field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); + field_total_size = field_data_size + sizeof(mz_uint16) * 2; + + if (field_total_size > extra_size_remaining) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + if (field_id != MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) + { + if (!mz_zip_array_push_back(pZip, pNew_ext, pExtra_data, field_total_size)) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + pExtra_data += field_total_size; + extra_size_remaining -= field_total_size; + } while (extra_size_remaining); + } + + return MZ_TRUE; +} + +/* TODO: This func is now pretty freakin complex due to zip64, split it up? */ +mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint src_file_index) +{ + mz_uint n, bit_flags, num_alignment_padding_bytes, src_central_dir_following_data_size; + mz_uint64 src_archive_bytes_remaining, local_dir_header_ofs; + mz_uint64 cur_src_file_ofs, cur_dst_file_ofs; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; + mz_uint8 new_central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; + size_t orig_central_dir_size; + mz_zip_internal_state *pState; + void *pBuf; + const mz_uint8 *pSrc_central_header; + mz_zip_archive_file_stat src_file_stat; + mz_uint32 src_filename_len, src_comment_len, src_ext_len; + mz_uint32 local_header_filename_size, local_header_extra_len; + mz_uint64 local_header_comp_size, local_header_uncomp_size; + mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE; + + /* Sanity checks */ + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pSource_zip->m_pRead)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + pState = pZip->m_pState; + + /* Don't support copying files from zip64 archives to non-zip64, even though in some cases this is possible */ + if ((pSource_zip->m_pState->m_zip64) && (!pZip->m_pState->m_zip64)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + /* Get pointer to the source central dir header and crack it */ + if (NULL == (pSrc_central_header = mz_zip_get_cdh(pSource_zip, src_file_index))) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_SIG_OFS) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + src_filename_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS); + src_comment_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS); + src_ext_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS); + src_central_dir_following_data_size = src_filename_len + src_ext_len + src_comment_len; + + /* TODO: We don't support central dir's >= MZ_UINT32_MAX bytes right now (+32 fudge factor in case we need to add more extra data) */ + if ((pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + 32) >= MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); + + num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); + + if (!pState->m_zip64) + { + if (pZip->m_total_files == MZ_UINT16_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + } + else + { + /* TODO: Our zip64 support still has some 32-bit limits that may not be worth fixing. */ + if (pZip->m_total_files == MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + } + + if (!mz_zip_file_stat_internal(pSource_zip, src_file_index, pSrc_central_header, &src_file_stat, NULL)) + return MZ_FALSE; + + cur_src_file_ofs = src_file_stat.m_local_header_ofs; + cur_dst_file_ofs = pZip->m_archive_size; + + /* Read the source archive's local dir header */ + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; + + /* Compute the total size we need to copy (filename+extra data+compressed data) */ + local_header_filename_size = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS); + local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS); + local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS); + src_archive_bytes_remaining = local_header_filename_size + local_header_extra_len + src_file_stat.m_comp_size; + + /* Try to find a zip64 extended information field */ + if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX))) + { + mz_zip_array file_data_array; + mz_zip_array_init(&file_data_array, 1); + if (!mz_zip_array_resize(pZip, &file_data_array, local_header_extra_len, MZ_FALSE)) + { + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, src_file_stat.m_local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_size, file_data_array.m_p, local_header_extra_len) != local_header_extra_len) + { + mz_zip_array_clear(pZip, &file_data_array); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + } + + mz_uint32 extra_size_remaining = local_header_extra_len; + const mz_uint8 *pExtra_data = (const mz_uint8 *)file_data_array.m_p; + + do + { + mz_uint32 field_id, field_data_size, field_total_size; + + if (extra_size_remaining < (sizeof(mz_uint16) * 2)) + { + mz_zip_array_clear(pZip, &file_data_array); + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } + + field_id = MZ_READ_LE16(pExtra_data); + field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); + field_total_size = field_data_size + sizeof(mz_uint16) * 2; + + if (field_total_size > extra_size_remaining) + { + mz_zip_array_clear(pZip, &file_data_array); + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } + + if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) + { + const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32); + + if (field_data_size < sizeof(mz_uint64) * 2) + { + mz_zip_array_clear(pZip, &file_data_array); + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } + + local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data); + local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64)); /* may be 0 if there's a descriptor */ + + found_zip64_ext_data_in_ldir = MZ_TRUE; + break; + } + + pExtra_data += field_total_size; + extra_size_remaining -= field_total_size; + } while (extra_size_remaining); + + mz_zip_array_clear(pZip, &file_data_array); + } + + if (!pState->m_zip64) + { + /* Try to detect if the new archive will most likely wind up too big and bail early (+(sizeof(mz_uint32) * 4) is for the optional descriptor which could be present, +64 is a fudge factor). */ + /* We also check when the archive is finalized so this doesn't need to be perfect. */ + mz_uint64 approx_new_archive_size = cur_dst_file_ofs + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + src_archive_bytes_remaining + (sizeof(mz_uint32) * 4) + + pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 64; + + if (approx_new_archive_size >= MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + } + + /* Write dest archive padding */ + if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes)) + return MZ_FALSE; + + cur_dst_file_ofs += num_alignment_padding_bytes; + + local_dir_header_ofs = cur_dst_file_ofs; + if (pZip->m_file_offset_alignment) + { + MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); + } + + /* The original zip's local header+ext block doesn't change, even with zip64, so we can just copy it over to the dest zip */ + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; + + /* Copy over the source archive bytes to the dest archive, also ensure we have enough buf space to handle optional data descriptor */ + if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(32U, MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining))))) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + while (src_archive_bytes_remaining) + { + n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining); + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + } + cur_src_file_ofs += n; + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + cur_dst_file_ofs += n; + + src_archive_bytes_remaining -= n; + } + + /* Now deal with the optional data descriptor */ + bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS); + if (bit_flags & 8) + { + /* Copy data descriptor */ + if ((pSource_zip->m_pState->m_zip64) || (found_zip64_ext_data_in_ldir)) + { + /* src is zip64, dest must be zip64 */ + + /* name uint32_t's */ + /* id 1 (optional in zip64?) */ + /* crc 1 */ + /* comp_size 2 */ + /* uncomp_size 2 */ + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, (sizeof(mz_uint32) * 6)) != (sizeof(mz_uint32) * 6)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + } + + n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID) ? 6 : 5); + } + else + { + /* src is NOT zip64 */ + mz_bool has_id; + + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + } + + has_id = (MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID); + + if (pZip->m_pState->m_zip64) + { + /* dest is zip64, so upgrade the data descriptor */ + const mz_uint32 *pSrc_descriptor = (const mz_uint32 *)((const mz_uint8 *)pBuf + (has_id ? sizeof(mz_uint32) : 0)); + const mz_uint32 src_crc32 = pSrc_descriptor[0]; + const mz_uint64 src_comp_size = pSrc_descriptor[1]; + const mz_uint64 src_uncomp_size = pSrc_descriptor[2]; + + mz_write_le32((mz_uint8 *)pBuf, MZ_ZIP_DATA_DESCRIPTOR_ID); + mz_write_le32((mz_uint8 *)pBuf + sizeof(mz_uint32) * 1, src_crc32); + mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 2, src_comp_size); + mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 4, src_uncomp_size); + + n = sizeof(mz_uint32) * 6; + } + else + { + /* dest is NOT zip64, just copy it as-is */ + n = sizeof(mz_uint32) * (has_id ? 4 : 3); + } + } + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + + cur_src_file_ofs += n; + cur_dst_file_ofs += n; + } + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + + /* Finally, add the new central dir header */ + orig_central_dir_size = pState->m_central_dir.m_size; + + memcpy(new_central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); + + if (pState->m_zip64) + { + /* This is the painful part: We need to write a new central dir header + ext block with updated zip64 fields, and ensure the old fields (if any) are not included. */ + const mz_uint8 *pSrc_ext = pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len; + mz_zip_array new_ext_block; + + mz_zip_array_init(&new_ext_block, sizeof(mz_uint8)); + + MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_UINT32_MAX); + MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_UINT32_MAX); + MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_UINT32_MAX); + + if (!mz_zip_writer_update_zip64_extension_block(&new_ext_block, pZip, pSrc_ext, src_ext_len, &src_file_stat.m_comp_size, &src_file_stat.m_uncomp_size, &local_dir_header_ofs, NULL)) + { + mz_zip_array_clear(pZip, &new_ext_block); + return MZ_FALSE; + } + + MZ_WRITE_LE16(new_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS, new_ext_block.m_size); + + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) + { + mz_zip_array_clear(pZip, &new_ext_block); + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_filename_len)) + { + mz_zip_array_clear(pZip, &new_ext_block); + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_ext_block.m_p, new_ext_block.m_size)) + { + mz_zip_array_clear(pZip, &new_ext_block); + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len + src_ext_len, src_comment_len)) + { + mz_zip_array_clear(pZip, &new_ext_block); + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + mz_zip_array_clear(pZip, &new_ext_block); + } + else + { + /* sanity checks */ + if (cur_dst_file_ofs > MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + + if (local_dir_header_ofs >= MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + + MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs); + + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_central_dir_following_data_size)) + { + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + } + + /* This shouldn't trigger unless we screwed up during the initial sanity checks */ + if (pState->m_central_dir.m_size >= MZ_UINT32_MAX) + { + /* TODO: Support central dirs >= 32-bits in size */ + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); + } + + n = (mz_uint32)orig_central_dir_size; + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) + { + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + pZip->m_total_files++; + pZip->m_archive_size = cur_dst_file_ofs; + + return MZ_TRUE; +} + +mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) +{ + mz_zip_internal_state *pState; + mz_uint64 central_dir_ofs, central_dir_size; + mz_uint8 hdr[256]; + + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + pState = pZip->m_pState; + + if (pState->m_zip64) + { + if ((pZip->m_total_files > MZ_UINT32_MAX) || (pState->m_central_dir.m_size >= MZ_UINT32_MAX)) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + } + else + { + if ((pZip->m_total_files > MZ_UINT16_MAX) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX)) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + } + + central_dir_ofs = 0; + central_dir_size = 0; + if (pZip->m_total_files) + { + /* Write central directory */ + central_dir_ofs = pZip->m_archive_size; + central_dir_size = pState->m_central_dir.m_size; + pZip->m_central_directory_file_ofs = central_dir_ofs; + if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + pZip->m_archive_size += central_dir_size; + } + + if (pState->m_zip64) + { + /* Write zip64 end of central directory header */ + mz_uint64 rel_ofs_to_zip64_ecdr = pZip->m_archive_size; + + MZ_CLEAR_OBJ(hdr); + MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDH_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG); + MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - sizeof(mz_uint32) - sizeof(mz_uint64)); + MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS, 0x031E); /* TODO: always Unix */ + MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_NEEDED_OFS, 0x002D); + MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files); + MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files); + MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_SIZE_OFS, central_dir_size); + MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_OFS_OFS, central_dir_ofs); + if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE; + + /* Write zip64 end of central directory locator */ + MZ_CLEAR_OBJ(hdr); + MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG); + MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS, rel_ofs_to_zip64_ecdr); + MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS, 1); + if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE; + } + + /* Write end of central directory record */ + MZ_CLEAR_OBJ(hdr); + MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG); + MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files)); + MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files)); + MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_size)); + MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_ofs)); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + +#ifndef MINIZ_NO_STDIO + if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF)) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED); +#endif /* #ifndef MINIZ_NO_STDIO */ + + pZip->m_archive_size += MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE; + + pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED; + return MZ_TRUE; +} + +mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf, size_t *pSize) +{ + if ((!ppBuf) || (!pSize)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + *ppBuf = NULL; + *pSize = 0; + + if ((!pZip) || (!pZip->m_pState)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (pZip->m_pWrite != mz_zip_heap_write_func) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (!mz_zip_writer_finalize_archive(pZip)) + return MZ_FALSE; + + *ppBuf = pZip->m_pState->m_pMem; + *pSize = pZip->m_pState->m_mem_size; + pZip->m_pState->m_pMem = NULL; + pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0; + + return MZ_TRUE; +} + +mz_bool mz_zip_writer_end(mz_zip_archive *pZip) +{ + return mz_zip_writer_end_internal(pZip, MZ_TRUE); +} + +#ifndef MINIZ_NO_STDIO +mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) +{ + return mz_zip_add_mem_to_archive_file_in_place_v2(pZip_filename, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, NULL); +} + +mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_zip_error *pErr) +{ + mz_bool status, created_new_archive = MZ_FALSE; + mz_zip_archive zip_archive; + struct MZ_FILE_STAT_STRUCT file_stat; + mz_zip_error actual_err = MZ_ZIP_NO_ERROR; + + mz_zip_zero_struct(&zip_archive); + if ((int)level_and_flags < 0) + level_and_flags = MZ_DEFAULT_LEVEL; + + if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION)) + { + if (pErr) + *pErr = MZ_ZIP_INVALID_PARAMETER; + return MZ_FALSE; + } + + if (!mz_zip_writer_validate_archive_name(pArchive_name)) + { + if (pErr) + *pErr = MZ_ZIP_INVALID_FILENAME; + return MZ_FALSE; + } + + /* Important: The regular non-64 bit version of stat() can fail here if the file is very large, which could cause the archive to be overwritten. */ + /* So be sure to compile with _LARGEFILE64_SOURCE 1 */ + if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) + { + /* Create a new archive. */ + if (!mz_zip_writer_init_file_v2(&zip_archive, pZip_filename, 0, level_and_flags)) + { + if (pErr) + *pErr = zip_archive.m_last_error; + return MZ_FALSE; + } + + created_new_archive = MZ_TRUE; + } + else + { + /* Append to an existing archive. */ + if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0)) + { + if (pErr) + *pErr = zip_archive.m_last_error; + return MZ_FALSE; + } + + if (!mz_zip_writer_init_from_reader_v2(&zip_archive, pZip_filename, level_and_flags)) + { + if (pErr) + *pErr = zip_archive.m_last_error; + + mz_zip_reader_end_internal(&zip_archive, MZ_FALSE); + + return MZ_FALSE; + } + } + + status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0); + actual_err = zip_archive.m_last_error; + + /* Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) */ + if (!mz_zip_writer_finalize_archive(&zip_archive)) + { + if (!actual_err) + actual_err = zip_archive.m_last_error; + + status = MZ_FALSE; + } + + if (!mz_zip_writer_end_internal(&zip_archive, status)) + { + if (!actual_err) + actual_err = zip_archive.m_last_error; + + status = MZ_FALSE; + } + + if ((!status) && (created_new_archive)) + { + /* It's a new archive and something went wrong, so just delete it. */ + int ignoredStatus = MZ_DELETE_FILE(pZip_filename); + (void)ignoredStatus; + } + + if (pErr) + *pErr = actual_err; + + return status; +} + +void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const char *pArchive_name, const char *pComment, size_t *pSize, mz_uint flags, mz_zip_error *pErr) +{ + mz_uint32 file_index; + mz_zip_archive zip_archive; + void *p = NULL; + + if (pSize) + *pSize = 0; + + if ((!pZip_filename) || (!pArchive_name)) + { + if (pErr) + *pErr = MZ_ZIP_INVALID_PARAMETER; + + return NULL; + } + + mz_zip_zero_struct(&zip_archive); + if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0)) + { + if (pErr) + *pErr = zip_archive.m_last_error; + + return NULL; + } + + if (mz_zip_reader_locate_file_v2(&zip_archive, pArchive_name, pComment, flags, &file_index)) + { + p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags); + } + + mz_zip_reader_end_internal(&zip_archive, p != NULL); + + if (pErr) + *pErr = zip_archive.m_last_error; + + return p; +} + +void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags) +{ + return mz_zip_extract_archive_file_to_heap_v2(pZip_filename, pArchive_name, NULL, pSize, flags, NULL); +} + +#endif /* #ifndef MINIZ_NO_STDIO */ + +#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS */ + +/* ------------------- Misc utils */ + +mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip) +{ + return pZip ? pZip->m_zip_mode : MZ_ZIP_MODE_INVALID; +} + +mz_zip_type mz_zip_get_type(mz_zip_archive *pZip) +{ + return pZip ? pZip->m_zip_type : MZ_ZIP_TYPE_INVALID; +} + +mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num) +{ + mz_zip_error prev_err; + + if (!pZip) + return MZ_ZIP_INVALID_PARAMETER; + + prev_err = pZip->m_last_error; + + pZip->m_last_error = err_num; + return prev_err; +} + +mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip) +{ + if (!pZip) + return MZ_ZIP_INVALID_PARAMETER; + + return pZip->m_last_error; +} + +mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip) +{ + return mz_zip_set_last_error(pZip, MZ_ZIP_NO_ERROR); +} + +mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip) +{ + mz_zip_error prev_err; + + if (!pZip) + return MZ_ZIP_INVALID_PARAMETER; + + prev_err = pZip->m_last_error; + + pZip->m_last_error = MZ_ZIP_NO_ERROR; + return prev_err; +} + +const char *mz_zip_get_error_string(mz_zip_error mz_err) +{ + switch (mz_err) + { + case MZ_ZIP_NO_ERROR: + return "no error"; + case MZ_ZIP_UNDEFINED_ERROR: + return "undefined error"; + case MZ_ZIP_TOO_MANY_FILES: + return "too many files"; + case MZ_ZIP_FILE_TOO_LARGE: + return "file too large"; + case MZ_ZIP_UNSUPPORTED_METHOD: + return "unsupported method"; + case MZ_ZIP_UNSUPPORTED_ENCRYPTION: + return "unsupported encryption"; + case MZ_ZIP_UNSUPPORTED_FEATURE: + return "unsupported feature"; + case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR: + return "failed finding central directory"; + case MZ_ZIP_NOT_AN_ARCHIVE: + return "not a ZIP archive"; + case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED: + return "invalid header or archive is corrupted"; + case MZ_ZIP_UNSUPPORTED_MULTIDISK: + return "unsupported multidisk archive"; + case MZ_ZIP_DECOMPRESSION_FAILED: + return "decompression failed or archive is corrupted"; + case MZ_ZIP_COMPRESSION_FAILED: + return "compression failed"; + case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE: + return "unexpected decompressed size"; + case MZ_ZIP_CRC_CHECK_FAILED: + return "CRC-32 check failed"; + case MZ_ZIP_UNSUPPORTED_CDIR_SIZE: + return "unsupported central directory size"; + case MZ_ZIP_ALLOC_FAILED: + return "allocation failed"; + case MZ_ZIP_FILE_OPEN_FAILED: + return "file open failed"; + case MZ_ZIP_FILE_CREATE_FAILED: + return "file create failed"; + case MZ_ZIP_FILE_WRITE_FAILED: + return "file write failed"; + case MZ_ZIP_FILE_READ_FAILED: + return "file read failed"; + case MZ_ZIP_FILE_CLOSE_FAILED: + return "file close failed"; + case MZ_ZIP_FILE_SEEK_FAILED: + return "file seek failed"; + case MZ_ZIP_FILE_STAT_FAILED: + return "file stat failed"; + case MZ_ZIP_INVALID_PARAMETER: + return "invalid parameter"; + case MZ_ZIP_INVALID_FILENAME: + return "invalid filename"; + case MZ_ZIP_BUF_TOO_SMALL: + return "buffer too small"; + case MZ_ZIP_INTERNAL_ERROR: + return "internal error"; + case MZ_ZIP_FILE_NOT_FOUND: + return "file not found"; + case MZ_ZIP_ARCHIVE_TOO_LARGE: + return "archive is too large"; + case MZ_ZIP_VALIDATION_FAILED: + return "validation failed"; + case MZ_ZIP_WRITE_CALLBACK_FAILED: + return "write calledback failed"; + default: + break; + } + + return "unknown error"; +} + +/* Note: Just because the archive is not zip64 doesn't necessarily mean it doesn't have Zip64 extended information extra field, argh. */ +mz_bool mz_zip_is_zip64(mz_zip_archive *pZip) +{ + if ((!pZip) || (!pZip->m_pState)) + return MZ_FALSE; + + return pZip->m_pState->m_zip64; +} + +size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip) +{ + if ((!pZip) || (!pZip->m_pState)) + return 0; + + return pZip->m_pState->m_central_dir.m_size; +} + +mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) +{ + return pZip ? pZip->m_total_files : 0; +} + +mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip) +{ + if (!pZip) + return 0; + return pZip->m_archive_size; +} + +mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip) +{ + if ((!pZip) || (!pZip->m_pState)) + return 0; + return pZip->m_pState->m_file_archive_start_ofs; +} + +MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip) +{ + if ((!pZip) || (!pZip->m_pState)) + return 0; + return pZip->m_pState->m_pFile; +} + +size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n) +{ + if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pZip->m_pRead)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + return pZip->m_pRead(pZip->m_pIO_opaque, file_ofs, pBuf, n); +} + +mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size) +{ + mz_uint n; + const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index); + if (!p) + { + if (filename_buf_size) + pFilename[0] = '\0'; + mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + return 0; + } + n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + if (filename_buf_size) + { + n = MZ_MIN(n, filename_buf_size - 1); + memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); + pFilename[n] = '\0'; + } + return n + 1; +} + +mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat) +{ + return mz_zip_file_stat_internal(pZip, file_index, mz_zip_get_cdh(pZip, file_index), pStat, NULL); +} + +mz_bool mz_zip_end(mz_zip_archive *pZip) +{ + if (!pZip) + return MZ_FALSE; + + if (pZip->m_zip_mode == MZ_ZIP_MODE_READING) + return mz_zip_reader_end(pZip); + else if ((pZip->m_zip_mode == MZ_ZIP_MODE_WRITING) || (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)) + return mz_zip_writer_end(pZip); + + return MZ_FALSE; +} + +#ifdef __cplusplus +} +#endif diff --git a/src/miniz/miniz.h b/src/miniz/miniz.h new file mode 100644 index 00000000000..daa6423c08b --- /dev/null +++ b/src/miniz/miniz.h @@ -0,0 +1,1352 @@ +/* miniz.c v1.16 beta r1 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing + See "unlicense" statement at the end of this file. + Rich Geldreich , last updated Oct. 13, 2013 + Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt + + Most API's defined in miniz.c are optional. For example, to disable the archive related functions just define + MINIZ_NO_ARCHIVE_APIS, or to get rid of all stdio usage define MINIZ_NO_STDIO (see the list below for more macros). + + * Change History + 10/19/13 v1.16 beta r1 - Two key inflator-only robustness and streaming related changes. Also merged in tdefl_compressor_alloc(), tdefl_compressor_free() helpers to make script bindings easier for rustyzip. + - The inflator coroutine func. is subtle and complex so I'm being cautious about this release. I would greatly appreciate any help with testing or any feedback. + I feel good about these changes, and they've been through several hours of automated testing, but they will probably not fix anything for the majority of prev. users so I'm + going to mark this release as beta for a few weeks and continue testing it at work/home on various things. + - The inflator in raw (non-zlib) mode is now usable on gzip or similiar data streams that have a bunch of bytes following the raw deflate data (problem discovered by rustyzip author williamw520). + This version should *never* read beyond the last byte of the raw deflate data independent of how many bytes you pass into the input buffer. This issue was caused by the various Huffman bitbuffer lookahead optimizations, and + would not be an issue if the caller knew and enforced the precise size of the raw compressed data *or* if the compressed data was in zlib format (i.e. always followed by the byte aligned zlib adler32). + So in other words, you can now call the inflator on deflate streams that are followed by arbitrary amounts of data and it's guaranteed that decompression will stop exactly on the last byte. + - The inflator now has a new failure status: TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS (-4). Previously, if the inflator was starved of bytes and could not make progress (because the input buffer was empty and the + caller did not set the TINFL_FLAG_HAS_MORE_INPUT flag - say on truncated or corrupted compressed data stream) it would append all 0's to the input and try to soldier on. + This is scary, because in the worst case, I believe it was possible for the prev. inflator to start outputting large amounts of literal data. If the caller didn't know when to stop accepting output + (because it didn't know how much uncompressed data was expected, or didn't enforce a sane maximum) it could continue forever. v1.16 cannot fall into this failure mode, instead it'll return + TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS immediately if it needs 1 or more bytes to make progress, the input buf is empty, and the caller has indicated that no more input is available. This is a "soft" + failure, so you can call the inflator again with more input and it will try to continue, or you can give up and fail. This could be very useful in network streaming scenarios. + - Added documentation to all the tinfl return status codes, fixed miniz_tester so it accepts double minus params for Linux, tweaked example1.c, added a simple "follower bytes" test to miniz_tester.cpp. + 10/13/13 v1.15 r4 - Interim bugfix release while I work on the next major release with Zip64 support (almost there!): + - Critical fix for the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug (thanks kahmyong.moon@hp.com) which could cause locate files to not find files. This bug + would only have occured in earlier versions if you explicitly used this flag, OR if you used mz_zip_extract_archive_file_to_heap() or mz_zip_add_mem_to_archive_file_in_place() + (which used this flag). If you can't switch to v1.15 but want to fix this bug, just remove the uses of this flag from both helper funcs (and of course don't use the flag). + - Bugfix in mz_zip_reader_extract_to_mem_no_alloc() from kymoon when pUser_read_buf is not NULL and compressed size is > uncompressed size + - Fixing mz_zip_reader_extract_*() funcs so they don't try to extract compressed data from directory entries, to account for weird zipfiles which contain zero-size compressed data on dir entries. + Hopefully this fix won't cause any issues on weird zip archives, because it assumes the low 16-bits of zip external attributes are DOS attributes (which I believe they always are in practice). + - Fixing mz_zip_reader_is_file_a_directory() so it doesn't check the internal attributes, just the filename and external attributes + - mz_zip_reader_init_file() - missing MZ_FCLOSE() call if the seek failed + - Added cmake support for Linux builds which builds all the examples, tested with clang v3.3 and gcc v4.6. + - Clang fix for tdefl_write_image_to_png_file_in_memory() from toffaletti + - Merged MZ_FORCEINLINE fix from hdeanclark + - Fix include before config #ifdef, thanks emil.brink + - Added tdefl_write_image_to_png_file_in_memory_ex(): supports Y flipping (super useful for OpenGL apps), and explicit control over the compression level (so you can + set it to 1 for real-time compression). + - Merged in some compiler fixes from paulharris's github repro. + - Retested this build under Windows (VS 2010, including static analysis), tcc 0.9.26, gcc v4.6 and clang v3.3. + - Added example6.c, which dumps an image of the mandelbrot set to a PNG file. + - Modified example2 to help test the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY flag more. + - In r3: Bugfix to mz_zip_writer_add_file() found during merge: Fix possible src file fclose() leak if alignment bytes+local header file write faiiled + - In r4: Minor bugfix to mz_zip_writer_add_from_zip_reader(): Was pushing the wrong central dir header offset, appears harmless in this release, but it became a problem in the zip64 branch + 5/20/12 v1.14 - MinGW32/64 GCC 4.6.1 compiler fixes: added MZ_FORCEINLINE, #include (thanks fermtect). + 5/19/12 v1.13 - From jason@cornsyrup.org and kelwert@mtu.edu - Fix mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit. + - Temporarily/locally slammed in "typedef unsigned long mz_ulong" and re-ran a randomized regression test on ~500k files. + - Eliminated a bunch of warnings when compiling with GCC 32-bit/64. + - Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze (static analysis) option and fixed all warnings (except for the silly + "Use of the comma-operator in a tested expression.." analysis warning, which I purposely use to work around a MSVC compiler warning). + - Created 32-bit and 64-bit Codeblocks projects/workspace. Built and tested Linux executables. The codeblocks workspace is compatible with Linux+Win32/x64. + - Added miniz_tester solution/project, which is a useful little app derived from LZHAM's tester app that I use as part of the regression test. + - Ran miniz.c and tinfl.c through another series of regression testing on ~500,000 files and archives. + - Modified example5.c so it purposely disables a bunch of high-level functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the MINIZ_NO_STDIO bug report.) + - Fix ftell() usage in examples so they exit with an error on files which are too large (a limitation of the examples, not miniz itself). + 4/12/12 v1.12 - More comments, added low-level example5.c, fixed a couple minor level_and_flags issues in the archive API's. + level_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson for the feedback/bug report. + 5/28/11 v1.11 - Added statement from unlicense.org + 5/27/11 v1.10 - Substantial compressor optimizations: + - Level 1 is now ~4x faster than before. The L1 compressor's throughput now varies between 70-110MB/sec. on a + - Core i7 (actual throughput varies depending on the type of data, and x64 vs. x86). + - Improved baseline L2-L9 compression perf. Also, greatly improved compression perf. issues on some file types. + - Refactored the compression code for better readability and maintainability. + - Added level 10 compression level (L10 has slightly better ratio than level 9, but could have a potentially large + drop in throughput on some files). + 5/15/11 v1.09 - Initial stable release. + + * Low-level Deflate/Inflate implementation notes: + + Compression: Use the "tdefl" API's. The compressor supports raw, static, and dynamic blocks, lazy or + greedy parsing, match length filtering, RLE-only, and Huffman-only streams. It performs and compresses + approximately as well as zlib. + + Decompression: Use the "tinfl" API's. The entire decompressor is implemented as a single function + coroutine: see tinfl_decompress(). It supports decompression into a 32KB (or larger power of 2) wrapping buffer, or into a memory + block large enough to hold the entire file. + + The low-level tdefl/tinfl API's do not make any use of dynamic memory allocation. + + * zlib-style API notes: + + miniz.c implements a fairly large subset of zlib. There's enough functionality present for it to be a drop-in + zlib replacement in many apps: + The z_stream struct, optional memory allocation callbacks + deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound + inflateInit/inflateInit2/inflate/inflateEnd + compress, compress2, compressBound, uncompress + CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly routines. + Supports raw deflate streams or standard zlib streams with adler-32 checking. + + Limitations: + The callback API's are not implemented yet. No support for gzip headers or zlib static dictionaries. + I've tried to closely emulate zlib's various flavors of stream flushing and return status codes, but + there are no guarantees that miniz.c pulls this off perfectly. + + * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function, originally written by + Alex Evans. Supports 1-4 bytes/pixel images. + + * ZIP archive API notes: + + The ZIP archive API's where designed with simplicity and efficiency in mind, with just enough abstraction to + get the job done with minimal fuss. There are simple API's to retrieve file information, read files from + existing archives, create new archives, append new files to existing archives, or clone archive data from + one archive to another. It supports archives located in memory or the heap, on disk (using stdio.h), + or you can specify custom file read/write callbacks. + + - Archive reading: Just call this function to read a single file from a disk archive: + + void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, + size_t *pSize, mz_uint zip_flags); + + For more complex cases, use the "mz_zip_reader" functions. Upon opening an archive, the entire central + directory is located and read as-is into memory, and subsequent file access only occurs when reading individual files. + + - Archives file scanning: The simple way is to use this function to scan a loaded archive for a specific file: + + int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); + + The locate operation can optionally check file comments too, which (as one example) can be used to identify + multiple versions of the same file in an archive. This function uses a simple linear search through the central + directory, so it's not very fast. + + Alternately, you can iterate through all the files in an archive (using mz_zip_reader_get_num_files()) and + retrieve detailed info on each file by calling mz_zip_reader_file_stat(). + + - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer immediately writes compressed file data + to disk and builds an exact image of the central directory in memory. The central directory image is written + all at once at the end of the archive file when the archive is finalized. + + The archive writer can optionally align each file's local header and file data to any power of 2 alignment, + which can be useful when the archive will be read from optical media. Also, the writer supports placing + arbitrary data blobs at the very beginning of ZIP archives. Archives written using either feature are still + readable by any ZIP tool. + + - Archive appending: The simple way to add a single file to an archive is to call this function: + + mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, + const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); + + The archive will be created if it doesn't already exist, otherwise it'll be appended to. + Note the appending is done in-place and is not an atomic operation, so if something goes wrong + during the operation it's possible the archive could be left without a central directory (although the local + file headers and file data will be fine, so the archive will be recoverable). + + For more complex archive modification scenarios: + 1. The safest way is to use a mz_zip_reader to read the existing archive, cloning only those bits you want to + preserve into a new archive using using the mz_zip_writer_add_from_zip_reader() function (which compiles the + compressed file data as-is). When you're done, delete the old archive and rename the newly written archive, and + you're done. This is safe but requires a bunch of temporary disk space or heap memory. + + 2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using mz_zip_writer_init_from_reader(), + append new files as needed, then finalize the archive which will write an updated central directory to the + original archive. (This is basically what mz_zip_add_mem_to_archive_file_in_place() does.) There's a + possibility that the archive's central directory could be lost with this method if anything goes wrong, though. + + - ZIP archive support limitations: + No zip64 or spanning support. Extraction functions can only handle unencrypted, stored or deflated files. + Requires streams capable of seeking. + + * This is a header file library, like stb_image.c. To get only a header file, either cut and paste the + below header, or create miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it. + + * Important: For best perf. be sure to customize the below macros for your target platform: + #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 + #define MINIZ_LITTLE_ENDIAN 1 + #define MINIZ_HAS_64BIT_REGISTERS 1 + + * On platforms using glibc, Be sure to "#define _LARGEFILE64_SOURCE 1" before including miniz.c to ensure miniz + uses the 64-bit variants: fopen64(), stat64(), etc. Otherwise you won't be able to process large files + (i.e. 32-bit stat() fails for me on files > 0x7FFFFFFF bytes). +*/ +#pragma once + + + + + +/* Defines to completely disable specific portions of miniz.c: + If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl. */ + +/* Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O. */ +/*#define MINIZ_NO_STDIO */ + +/* If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or */ +/* get/set file times, and the C run-time funcs that get/set times won't be called. */ +/* The current downside is the times written to your archives will be from 1979. */ +/*#define MINIZ_NO_TIME */ + +/* Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's. */ +/*#define MINIZ_NO_ARCHIVE_APIS */ + +/* Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive API's. */ +/*#define MINIZ_NO_ARCHIVE_WRITING_APIS */ + +/* Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression API's. */ +/*#define MINIZ_NO_ZLIB_APIS */ + +/* Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib. */ +/*#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES */ + +/* Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc. + Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc + callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user + functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work. */ +/*#define MINIZ_NO_MALLOC */ + +#if defined(__TINYC__) && (defined(__linux) || defined(__linux__)) +/* TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc on Linux */ +#define MINIZ_NO_TIME +#endif + +#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS) +#include +#endif + +#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__) +/* MINIZ_X86_OR_X64_CPU is only used to help set the below macros. */ +#define MINIZ_X86_OR_X64_CPU 1 +#endif + +#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU +/* Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian. */ +#define MINIZ_LITTLE_ENDIAN 1 +#endif + +#if MINIZ_X86_OR_X64_CPU +/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. */ +#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 +#endif + +#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__) +/* Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions). */ +#define MINIZ_HAS_64BIT_REGISTERS 1 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------- zlib-style API Definitions. */ + +/* For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits! */ +typedef unsigned long mz_ulong; + +/* mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap. */ +void mz_free(void *p); + +#define MZ_ADLER32_INIT (1) +/* mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL. */ +mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len); + +#define MZ_CRC32_INIT (0) +/* mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL. */ +mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len); + +/* Compression strategies. */ +enum +{ + MZ_DEFAULT_STRATEGY = 0, + MZ_FILTERED = 1, + MZ_HUFFMAN_ONLY = 2, + MZ_RLE = 3, + MZ_FIXED = 4 +}; + +/* Method */ +#define MZ_DEFLATED 8 + +#ifndef MINIZ_NO_ZLIB_APIS + +/* Heap allocation callbacks. + Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long. */ +typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size); +typedef void (*mz_free_func)(void *opaque, void *address); +typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size); + +/* TODO: I can't encode "1.16" here, argh */ +#define MZ_VERSION "9.1.15" +#define MZ_VERNUM 0x91F0 +#define MZ_VER_MAJOR 9 +#define MZ_VER_MINOR 1 +#define MZ_VER_REVISION 15 +#define MZ_VER_SUBREVISION 0 + +/* Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs). */ +enum +{ + MZ_NO_FLUSH = 0, + MZ_PARTIAL_FLUSH = 1, + MZ_SYNC_FLUSH = 2, + MZ_FULL_FLUSH = 3, + MZ_FINISH = 4, + MZ_BLOCK = 5 +}; + +/* Return status codes. MZ_PARAM_ERROR is non-standard. */ +enum +{ + MZ_OK = 0, + MZ_STREAM_END = 1, + MZ_NEED_DICT = 2, + MZ_ERRNO = -1, + MZ_STREAM_ERROR = -2, + MZ_DATA_ERROR = -3, + MZ_MEM_ERROR = -4, + MZ_BUF_ERROR = -5, + MZ_VERSION_ERROR = -6, + MZ_PARAM_ERROR = -10000 +}; + +/* Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL. */ +enum +{ + MZ_NO_COMPRESSION = 0, + MZ_BEST_SPEED = 1, + MZ_BEST_COMPRESSION = 9, + MZ_UBER_COMPRESSION = 10, + MZ_DEFAULT_LEVEL = 6, + MZ_DEFAULT_COMPRESSION = -1 +}; + +/* Window bits */ +#define MZ_DEFAULT_WINDOW_BITS 15 + +struct mz_internal_state; + +/* Compression/decompression stream struct. */ +typedef struct mz_stream_s +{ + const unsigned char *next_in; /* pointer to next byte to read */ + unsigned int avail_in; /* number of bytes available at next_in */ + mz_ulong total_in; /* total number of bytes consumed so far */ + + unsigned char *next_out; /* pointer to next byte to write */ + unsigned int avail_out; /* number of bytes that can be written to next_out */ + mz_ulong total_out; /* total number of bytes produced so far */ + + char *msg; /* error msg (unused) */ + struct mz_internal_state *state; /* internal state, allocated by zalloc/zfree */ + + mz_alloc_func zalloc; /* optional heap allocation function (defaults to malloc) */ + mz_free_func zfree; /* optional heap free function (defaults to free) */ + void *opaque; /* heap alloc function user pointer */ + + int data_type; /* data_type (unused) */ + mz_ulong adler; /* adler32 of the source or uncompressed data */ + mz_ulong reserved; /* not used */ +} mz_stream; + +typedef mz_stream *mz_streamp; + +/* Returns the version string of miniz.c. */ +const char *mz_version(void); + +/* mz_deflateInit() initializes a compressor with default options: */ +/* Parameters: */ +/* pStream must point to an initialized mz_stream struct. */ +/* level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION]. */ +/* level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio. */ +/* (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.) */ +/* Return values: */ +/* MZ_OK on success. */ +/* MZ_STREAM_ERROR if the stream is bogus. */ +/* MZ_PARAM_ERROR if the input parameters are bogus. */ +/* MZ_MEM_ERROR on out of memory. */ +int mz_deflateInit(mz_streamp pStream, int level); + +/* mz_deflateInit2() is like mz_deflate(), except with more control: */ +/* Additional parameters: */ +/* method must be MZ_DEFLATED */ +/* window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer) */ +/* mem_level must be between [1, 9] (it's checked but ignored by miniz.c) */ +int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy); + +/* Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2(). */ +int mz_deflateReset(mz_streamp pStream); + +/* mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible. */ +/* Parameters: */ +/* pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. */ +/* flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH. */ +/* Return values: */ +/* MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full). */ +/* MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore. */ +/* MZ_STREAM_ERROR if the stream is bogus. */ +/* MZ_PARAM_ERROR if one of the parameters is invalid. */ +/* MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.) */ +int mz_deflate(mz_streamp pStream, int flush); + +/* mz_deflateEnd() deinitializes a compressor: */ +/* Return values: */ +/* MZ_OK on success. */ +/* MZ_STREAM_ERROR if the stream is bogus. */ +int mz_deflateEnd(mz_streamp pStream); + +/* mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH. */ +mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len); + +/* Single-call compression functions mz_compress() and mz_compress2(): */ +/* Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure. */ +int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); +int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level); + +/* mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress(). */ +mz_ulong mz_compressBound(mz_ulong source_len); + +/* Initializes a decompressor. */ +int mz_inflateInit(mz_streamp pStream); + +/* mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer: */ +/* window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate). */ +int mz_inflateInit2(mz_streamp pStream, int window_bits); + +/* Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible. */ +/* Parameters: */ +/* pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. */ +/* flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH. */ +/* On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster). */ +/* MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data. */ +/* Return values: */ +/* MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full. */ +/* MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified. */ +/* MZ_STREAM_ERROR if the stream is bogus. */ +/* MZ_DATA_ERROR if the deflate stream is invalid. */ +/* MZ_PARAM_ERROR if one of the parameters is invalid. */ +/* MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again */ +/* with more input data, or with more room in the output buffer (except when using single call decompression, described above). */ +int mz_inflate(mz_streamp pStream, int flush); + +/* Deinitializes a decompressor. */ +int mz_inflateEnd(mz_streamp pStream); + +/* Single-call decompression. */ +/* Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure. */ +int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); + +/* Returns a string description of the specified error code, or NULL if the error code is invalid. */ +const char *mz_error(int err); + +/* Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports. */ +/* Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project. */ +#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES +typedef unsigned char Byte; +typedef unsigned int uInt; +typedef mz_ulong uLong; +typedef Byte Bytef; +typedef uInt uIntf; +typedef char charf; +typedef int intf; +typedef void *voidpf; +typedef uLong uLongf; +typedef void *voidp; +typedef void *const voidpc; +#define Z_NULL 0 +#define Z_NO_FLUSH MZ_NO_FLUSH +#define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH +#define Z_SYNC_FLUSH MZ_SYNC_FLUSH +#define Z_FULL_FLUSH MZ_FULL_FLUSH +#define Z_FINISH MZ_FINISH +#define Z_BLOCK MZ_BLOCK +#define Z_OK MZ_OK +#define Z_STREAM_END MZ_STREAM_END +#define Z_NEED_DICT MZ_NEED_DICT +#define Z_ERRNO MZ_ERRNO +#define Z_STREAM_ERROR MZ_STREAM_ERROR +#define Z_DATA_ERROR MZ_DATA_ERROR +#define Z_MEM_ERROR MZ_MEM_ERROR +#define Z_BUF_ERROR MZ_BUF_ERROR +#define Z_VERSION_ERROR MZ_VERSION_ERROR +#define Z_PARAM_ERROR MZ_PARAM_ERROR +#define Z_NO_COMPRESSION MZ_NO_COMPRESSION +#define Z_BEST_SPEED MZ_BEST_SPEED +#define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION +#define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION +#define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY +#define Z_FILTERED MZ_FILTERED +#define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY +#define Z_RLE MZ_RLE +#define Z_FIXED MZ_FIXED +#define Z_DEFLATED MZ_DEFLATED +#define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS +#define alloc_func mz_alloc_func +#define free_func mz_free_func +#define internal_state mz_internal_state +#define z_stream mz_stream +#define deflateInit mz_deflateInit +#define deflateInit2 mz_deflateInit2 +#define deflateReset mz_deflateReset +#define deflate mz_deflate +#define deflateEnd mz_deflateEnd +#define deflateBound mz_deflateBound +#define compress mz_compress +#define compress2 mz_compress2 +#define compressBound mz_compressBound +#define inflateInit mz_inflateInit +#define inflateInit2 mz_inflateInit2 +#define inflate mz_inflate +#define inflateEnd mz_inflateEnd +#define uncompress mz_uncompress +#define crc32 mz_crc32 +#define adler32 mz_adler32 +#define MAX_WBITS 15 +#define MAX_MEM_LEVEL 9 +#define zError mz_error +#define ZLIB_VERSION MZ_VERSION +#define ZLIB_VERNUM MZ_VERNUM +#define ZLIB_VER_MAJOR MZ_VER_MAJOR +#define ZLIB_VER_MINOR MZ_VER_MINOR +#define ZLIB_VER_REVISION MZ_VER_REVISION +#define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION +#define zlibVersion mz_version +#define zlib_version mz_version() +#endif /* #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES */ + +#endif /* MINIZ_NO_ZLIB_APIS */ + +#ifdef __cplusplus +} +#endif +#pragma once +#include +#include +#include +#include + +/* ------------------- Types and macros */ +typedef unsigned char mz_uint8; +typedef signed short mz_int16; +typedef unsigned short mz_uint16; +typedef unsigned int mz_uint32; +typedef unsigned int mz_uint; +typedef int64_t mz_int64; +typedef uint64_t mz_uint64; +typedef int mz_bool; + +#define MZ_FALSE (0) +#define MZ_TRUE (1) + +/* Works around MSVC's spammy "warning C4127: conditional expression is constant" message. */ +#ifdef _MSC_VER +#define MZ_MACRO_END while (0, 0) +#else +#define MZ_MACRO_END while (0) +#endif + +#ifdef MINIZ_NO_STDIO +#define MZ_FILE void * +#else +#include +#define MZ_FILE FILE +#endif /* #ifdef MINIZ_NO_STDIO */ + +#ifdef MINIZ_NO_TIME +typedef struct mz_dummy_time_t_tag +{ + int m_dummy; +} mz_dummy_time_t; +#define MZ_TIME_T mz_dummy_time_t +#else +#define MZ_TIME_T time_t +#endif + +#define MZ_ASSERT(x) assert(x) + +#ifdef MINIZ_NO_MALLOC +#define MZ_MALLOC(x) NULL +#define MZ_FREE(x) (void) x, ((void)0) +#define MZ_REALLOC(p, x) NULL +#else +#define MZ_MALLOC(x) malloc(x) +#define MZ_FREE(x) free(x) +#define MZ_REALLOC(p, x) realloc(p, x) +#endif + +#define MZ_MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define MZ_MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj)) + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES &&MINIZ_LITTLE_ENDIAN +#define MZ_READ_LE16(p) *((const mz_uint16 *)(p)) +#define MZ_READ_LE32(p) *((const mz_uint32 *)(p)) +#else +#define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U)) +#define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U)) +#endif + +#define MZ_READ_LE64(p) (((mz_uint64)MZ_READ_LE32(p)) | (((mz_uint64)MZ_READ_LE32((const mz_uint8 *)(p) + sizeof(mz_uint32))) << 32U)) + +#ifdef _MSC_VER +#define MZ_FORCEINLINE __forceinline +#elif defined(__GNUC__) +#define MZ_FORCEINLINE __inline__ __attribute__((__always_inline__)) +#else +#define MZ_FORCEINLINE inline +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +extern void *miniz_def_alloc_func(void *opaque, size_t items, size_t size); +extern void miniz_def_free_func(void *opaque, void *address); +extern void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size); + +#define MZ_UINT16_MAX (0xFFFFU) +#define MZ_UINT32_MAX (0xFFFFFFFFU) + +#ifdef __cplusplus +} +#endif +#pragma once + + +#ifdef __cplusplus +extern "C" { +#endif +/* ------------------- Low-level Compression API Definitions */ + +/* Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently). */ +#define TDEFL_LESS_MEMORY 0 + +/* tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search): */ +/* TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression). */ +enum +{ + TDEFL_HUFFMAN_ONLY = 0, + TDEFL_DEFAULT_MAX_PROBES = 128, + TDEFL_MAX_PROBES_MASK = 0xFFF +}; + +/* TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data. */ +/* TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers). */ +/* TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing. */ +/* TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory). */ +/* TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1) */ +/* TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled. */ +/* TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables. */ +/* TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks. */ +/* The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK). */ +enum +{ + TDEFL_WRITE_ZLIB_HEADER = 0x01000, + TDEFL_COMPUTE_ADLER32 = 0x02000, + TDEFL_GREEDY_PARSING_FLAG = 0x04000, + TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000, + TDEFL_RLE_MATCHES = 0x10000, + TDEFL_FILTER_MATCHES = 0x20000, + TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000, + TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000 +}; + +/* High level compression functions: */ +/* tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc(). */ +/* On entry: */ +/* pSrc_buf, src_buf_len: Pointer and size of source block to compress. */ +/* flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression. */ +/* On return: */ +/* Function returns a pointer to the compressed data, or NULL on failure. */ +/* *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data. */ +/* The caller must free() the returned block when it's no longer needed. */ +void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); + +/* tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory. */ +/* Returns 0 on failure. */ +size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); + +/* Compresses an image to a compressed PNG file in memory. */ +/* On entry: */ +/* pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4. */ +/* The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory. */ +/* level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL */ +/* If flip is true, the image will be flipped on the Y axis (useful for OpenGL apps). */ +/* On return: */ +/* Function returns a pointer to the compressed data, or NULL on failure. */ +/* *pLen_out will be set to the size of the PNG image file. */ +/* The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed. */ +void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip); +void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out); + +/* Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time. */ +typedef mz_bool (*tdefl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser); + +/* tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally. */ +mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + +enum +{ + TDEFL_MAX_HUFF_TABLES = 3, + TDEFL_MAX_HUFF_SYMBOLS_0 = 288, + TDEFL_MAX_HUFF_SYMBOLS_1 = 32, + TDEFL_MAX_HUFF_SYMBOLS_2 = 19, + TDEFL_LZ_DICT_SIZE = 32768, + TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, + TDEFL_MIN_MATCH_LEN = 3, + TDEFL_MAX_MATCH_LEN = 258 +}; + +/* TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes). */ +#if TDEFL_LESS_MEMORY +enum +{ + TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, + TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10, + TDEFL_MAX_HUFF_SYMBOLS = 288, + TDEFL_LZ_HASH_BITS = 12, + TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, + TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, + TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS +}; +#else +enum +{ + TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, + TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10, + TDEFL_MAX_HUFF_SYMBOLS = 288, + TDEFL_LZ_HASH_BITS = 15, + TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, + TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, + TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS +}; +#endif + +/* The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions. */ +typedef enum +{ + TDEFL_STATUS_BAD_PARAM = -2, + TDEFL_STATUS_PUT_BUF_FAILED = -1, + TDEFL_STATUS_OKAY = 0, + TDEFL_STATUS_DONE = 1, +} tdefl_status; + +/* Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums */ +typedef enum +{ + TDEFL_NO_FLUSH = 0, + TDEFL_SYNC_FLUSH = 2, + TDEFL_FULL_FLUSH = 3, + TDEFL_FINISH = 4 +} tdefl_flush; + +/* tdefl's compression state structure. */ +typedef struct +{ + tdefl_put_buf_func_ptr m_pPut_buf_func; + void *m_pPut_buf_user; + mz_uint m_flags, m_max_probes[2]; + int m_greedy_parsing; + mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size; + mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end; + mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer; + mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish; + tdefl_status m_prev_return_status; + const void *m_pIn_buf; + void *m_pOut_buf; + size_t *m_pIn_buf_size, *m_pOut_buf_size; + tdefl_flush m_flush; + const mz_uint8 *m_pSrc; + size_t m_src_buf_left, m_out_buf_ofs; + mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1]; + mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE]; + mz_uint16 m_next[TDEFL_LZ_DICT_SIZE]; + mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE]; + mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE]; +} tdefl_compressor; + +/* Initializes the compressor. */ +/* There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory. */ +/* pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression. */ +/* If pBut_buf_func is NULL the user should always call the tdefl_compress() API. */ +/* flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.) */ +tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + +/* Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible. */ +tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush); + +/* tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr. */ +/* tdefl_compress_buffer() always consumes the entire input buffer. */ +tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush); + +tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d); +mz_uint32 tdefl_get_adler32(tdefl_compressor *d); + +/* Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't defined, because it uses some of its macros. */ +#ifndef MINIZ_NO_ZLIB_APIS +/* Create tdefl_compress() flags given zlib-style compression parameters. */ +/* level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files) */ +/* window_bits may be -15 (raw deflate) or 15 (zlib) */ +/* strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED */ +mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy); +#endif /* #ifndef MINIZ_NO_ZLIB_APIS */ + +/* Allocate the tdefl_compressor structure in C so that */ +/* non-C language bindings to tdefl_ API don't need to worry about */ +/* structure size and allocation mechanism. */ +tdefl_compressor *tdefl_compressor_alloc(); +void tdefl_compressor_free(tdefl_compressor *pComp); + +#ifdef __cplusplus +} +#endif +#pragma once + +/* ------------------- Low-level Decompression API Definitions */ + +#ifdef __cplusplus +extern "C" { +#endif +/* Decompression flags used by tinfl_decompress(). */ +/* TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream. */ +/* TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input. */ +/* TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB). */ +/* TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes. */ +enum +{ + TINFL_FLAG_PARSE_ZLIB_HEADER = 1, + TINFL_FLAG_HAS_MORE_INPUT = 2, + TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4, + TINFL_FLAG_COMPUTE_ADLER32 = 8 +}; + +/* High level decompression functions: */ +/* tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc(). */ +/* On entry: */ +/* pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress. */ +/* On return: */ +/* Function returns a pointer to the decompressed data, or NULL on failure. */ +/* *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data. */ +/* The caller must call mz_free() on the returned block when it's no longer needed. */ +void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); + +/* tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory. */ +/* Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success. */ +#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1)) +size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); + +/* tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer. */ +/* Returns 1 on success or 0 on failure. */ +typedef int (*tinfl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser); +int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + +struct tinfl_decompressor_tag; +typedef struct tinfl_decompressor_tag tinfl_decompressor; + +/* Allocate the tinfl_decompressor structure in C so that */ +/* non-C language bindings to tinfl_ API don't need to worry about */ +/* structure size and allocation mechanism. */ + +tinfl_decompressor *tinfl_decompressor_alloc(); +void tinfl_decompressor_free(tinfl_decompressor *pDecomp); + +/* Max size of LZ dictionary. */ +#define TINFL_LZ_DICT_SIZE 32768 + +/* Return status. */ +typedef enum +{ + /* This flags indicates the inflator needs 1 or more input bytes to make forward progress, but the caller is indicating that no more are available. The compressed data */ + /* is probably corrupted. If you call the inflator again with more bytes it'll try to continue processing the input but this is a BAD sign (either the data is corrupted or you called it incorrectly). */ + /* If you call it again with no input you'll just get TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS again. */ + TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS = -4, + + /* This flag indicates that one or more of the input parameters was obviously bogus. (You can try calling it again, but if you get this error the calling code is wrong.) */ + TINFL_STATUS_BAD_PARAM = -3, + + /* This flags indicate the inflator is finished but the adler32 check of the uncompressed data didn't match. If you call it again it'll return TINFL_STATUS_DONE. */ + TINFL_STATUS_ADLER32_MISMATCH = -2, + + /* This flags indicate the inflator has somehow failed (bad code, corrupted input, etc.). If you call it again without resetting via tinfl_init() it it'll just keep on returning the same status failure code. */ + TINFL_STATUS_FAILED = -1, + + /* Any status code less than TINFL_STATUS_DONE must indicate a failure. */ + + /* This flag indicates the inflator has returned every byte of uncompressed data that it can, has consumed every byte that it needed, has successfully reached the end of the deflate stream, and */ + /* if zlib headers and adler32 checking enabled that it has successfully checked the uncompressed data's adler32. If you call it again you'll just get TINFL_STATUS_DONE over and over again. */ + TINFL_STATUS_DONE = 0, + + /* This flag indicates the inflator MUST have more input data (even 1 byte) before it can make any more forward progress, or you need to clear the TINFL_FLAG_HAS_MORE_INPUT */ + /* flag on the next call if you don't have any more source data. If the source data was somehow corrupted it's also possible (but unlikely) for the inflator to keep on demanding input to */ + /* proceed, so be sure to properly set the TINFL_FLAG_HAS_MORE_INPUT flag. */ + TINFL_STATUS_NEEDS_MORE_INPUT = 1, + + /* This flag indicates the inflator definitely has 1 or more bytes of uncompressed data available, but it cannot write this data into the output buffer. */ + /* Note if the source compressed data was corrupted it's possible for the inflator to return a lot of uncompressed data to the caller. I've been assuming you know how much uncompressed data to expect */ + /* (either exact or worst case) and will stop calling the inflator and fail after receiving too much. In pure streaming scenarios where you have no idea how many bytes to expect this may not be possible */ + /* so I may need to add some code to address this. */ + TINFL_STATUS_HAS_MORE_OUTPUT = 2 +} tinfl_status; + +/* Initializes the decompressor to its initial state. */ +#define tinfl_init(r) \ + do \ + { \ + (r)->m_state = 0; \ + } \ + MZ_MACRO_END +#define tinfl_get_adler32(r) (r)->m_check_adler32 + +/* Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability. */ +/* This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output. */ +tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags); + +/* Internal/private bits follow. */ +enum +{ + TINFL_MAX_HUFF_TABLES = 3, + TINFL_MAX_HUFF_SYMBOLS_0 = 288, + TINFL_MAX_HUFF_SYMBOLS_1 = 32, + TINFL_MAX_HUFF_SYMBOLS_2 = 19, + TINFL_FAST_LOOKUP_BITS = 10, + TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS +}; + +typedef struct +{ + mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0]; + mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2]; +} tinfl_huff_table; + +#if MINIZ_HAS_64BIT_REGISTERS +#define TINFL_USE_64BIT_BITBUF 1 +#endif + +#if TINFL_USE_64BIT_BITBUF +typedef mz_uint64 tinfl_bit_buf_t; +#define TINFL_BITBUF_SIZE (64) +#else +typedef mz_uint32 tinfl_bit_buf_t; +#define TINFL_BITBUF_SIZE (32) +#endif + +struct tinfl_decompressor_tag +{ + mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES]; + tinfl_bit_buf_t m_bit_buf; + size_t m_dist_from_out_buf_start; + tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES]; + mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137]; +}; + +#ifdef __cplusplus +} +#endif + +#pragma once + + +/* ------------------- ZIP archive reading/writing */ + +#ifdef __cplusplus +extern "C" { +#endif + +enum +{ + /* Note: These enums can be reduced as needed to save memory or stack space - they are pretty conservative. */ + MZ_ZIP_MAX_IO_BUF_SIZE = 64 * 1024, + MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 512, + MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 512 +}; + +typedef struct +{ + /* Central directory file index. */ + mz_uint32 m_file_index; + + /* Byte offset of this entry in the archive's central directory. Note we currently only support up to UINT_MAX or less bytes in the central dir. */ + mz_uint64 m_central_dir_ofs; + + /* These fields are copied directly from the zip's central dir. */ + mz_uint16 m_version_made_by; + mz_uint16 m_version_needed; + mz_uint16 m_bit_flag; + mz_uint16 m_method; + +#ifndef MINIZ_NO_TIME + MZ_TIME_T m_time; +#endif + + /* CRC-32 of uncompressed data. */ + mz_uint32 m_crc32; + + /* File's compressed size. */ + mz_uint64 m_comp_size; + + /* File's uncompressed size. Note, I've seen some old archives where directory entries had 512 bytes for their uncompressed sizes, but when you try to unpack them you actually get 0 bytes. */ + mz_uint64 m_uncomp_size; + + /* Zip internal and external file attributes. */ + mz_uint16 m_internal_attr; + mz_uint32 m_external_attr; + + /* Entry's local header file offset in bytes. */ + mz_uint64 m_local_header_ofs; + + /* Size of comment in bytes. */ + mz_uint32 m_comment_size; + + /* MZ_TRUE if the entry appears to be a directory. */ + mz_bool m_is_directory; + + /* MZ_TRUE if the entry uses encryption/strong encryption (which miniz_zip doesn't support) */ + mz_bool m_is_encrypted; + + /* MZ_TRUE if the file is not encrypted, a patch file, and if it uses a compression method we support. */ + mz_bool m_is_supported; + + /* Filename. If string ends in '/' it's a subdirectory entry. */ + /* Guaranteed to be zero terminated, may be truncated to fit. */ + char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE]; + + /* Comment field. */ + /* Guaranteed to be zero terminated, may be truncated to fit. */ + char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE]; + +} mz_zip_archive_file_stat; + +typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n); +typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n); + +struct mz_zip_internal_state_tag; +typedef struct mz_zip_internal_state_tag mz_zip_internal_state; + +typedef enum +{ + MZ_ZIP_MODE_INVALID = 0, + MZ_ZIP_MODE_READING = 1, + MZ_ZIP_MODE_WRITING = 2, + MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3 +} mz_zip_mode; + +typedef enum +{ + MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100, + MZ_ZIP_FLAG_IGNORE_PATH = 0x0200, + MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400, + MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800, + MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG = 0x1000, /* if enabled, mz_zip_reader_locate_file() will be called on each file as its validated to ensure the func finds the file in the central dir (intended for testing) */ + MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY = 0x2000, /* validate the local headers, but don't decompress the entire file and check the crc32 */ + MZ_ZIP_FLAG_WRITE_ZIP64 = 0x4000, /* use the zip64 file format, instead of the original zip file format */ + MZ_ZIP_FLAG_WRITE_ALLOW_READING = 0x8000, + MZ_ZIP_FLAG_UTF8_FILENAME = 0x10000 +} mz_zip_flags; + +typedef enum +{ + MZ_ZIP_TYPE_INVALID = 0, + MZ_ZIP_TYPE_USER, + MZ_ZIP_TYPE_MEMORY, + MZ_ZIP_TYPE_HEAP, + MZ_ZIP_TYPE_FILE, + MZ_ZIP_TYPE_CFILE, + MZ_ZIP_TOTAL_TYPES +} mz_zip_type; + +/* miniz error codes. Be sure to update mz_zip_get_error_string() if you add or modify this enum. */ +typedef enum +{ + MZ_ZIP_NO_ERROR = 0, + MZ_ZIP_UNDEFINED_ERROR, + MZ_ZIP_TOO_MANY_FILES, + MZ_ZIP_FILE_TOO_LARGE, + MZ_ZIP_UNSUPPORTED_METHOD, + MZ_ZIP_UNSUPPORTED_ENCRYPTION, + MZ_ZIP_UNSUPPORTED_FEATURE, + MZ_ZIP_FAILED_FINDING_CENTRAL_DIR, + MZ_ZIP_NOT_AN_ARCHIVE, + MZ_ZIP_INVALID_HEADER_OR_CORRUPTED, + MZ_ZIP_UNSUPPORTED_MULTIDISK, + MZ_ZIP_DECOMPRESSION_FAILED, + MZ_ZIP_COMPRESSION_FAILED, + MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE, + MZ_ZIP_CRC_CHECK_FAILED, + MZ_ZIP_UNSUPPORTED_CDIR_SIZE, + MZ_ZIP_ALLOC_FAILED, + MZ_ZIP_FILE_OPEN_FAILED, + MZ_ZIP_FILE_CREATE_FAILED, + MZ_ZIP_FILE_WRITE_FAILED, + MZ_ZIP_FILE_READ_FAILED, + MZ_ZIP_FILE_CLOSE_FAILED, + MZ_ZIP_FILE_SEEK_FAILED, + MZ_ZIP_FILE_STAT_FAILED, + MZ_ZIP_INVALID_PARAMETER, + MZ_ZIP_INVALID_FILENAME, + MZ_ZIP_BUF_TOO_SMALL, + MZ_ZIP_INTERNAL_ERROR, + MZ_ZIP_FILE_NOT_FOUND, + MZ_ZIP_ARCHIVE_TOO_LARGE, + MZ_ZIP_VALIDATION_FAILED, + MZ_ZIP_WRITE_CALLBACK_FAILED, + MZ_ZIP_TOTAL_ERRORS +} mz_zip_error; + +typedef struct +{ + mz_uint64 m_archive_size; + mz_uint64 m_central_directory_file_ofs; + + /* We only support up to UINT32_MAX files in zip64 mode. */ + mz_uint32 m_total_files; + mz_zip_mode m_zip_mode; + mz_zip_type m_zip_type; + mz_zip_error m_last_error; + + mz_uint64 m_file_offset_alignment; + + mz_alloc_func m_pAlloc; + mz_free_func m_pFree; + mz_realloc_func m_pRealloc; + void *m_pAlloc_opaque; + + mz_file_read_func m_pRead; + mz_file_write_func m_pWrite; + void *m_pIO_opaque; + + mz_zip_internal_state *m_pState; + +} mz_zip_archive; + +/* -------- ZIP reading */ + +/* Inits a ZIP archive reader. */ +/* These functions read and validate the archive's central directory. */ +mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags); + +mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags); + +#ifndef MINIZ_NO_STDIO +/* Read a archive from a disk file. */ +/* file_start_ofs is the file offset where the archive actually begins, or 0. */ +/* actual_archive_size is the true total size of the archive, which may be smaller than the file's actual size on disk. If zero the entire file is treated as the archive. */ +mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags); +mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags, mz_uint64 file_start_ofs, mz_uint64 archive_size); + +/* Read an archive from an already opened FILE, beginning at the current file position. */ +/* The archive is assumed to be archive_size bytes long. If archive_size is < 0, then the entire rest of the file is assumed to contain the archive. */ +/* The FILE will NOT be closed when mz_zip_reader_end() is called. */ +mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 archive_size, mz_uint flags); +#endif + +/* Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used. */ +mz_bool mz_zip_reader_end(mz_zip_archive *pZip); + +/* -------- ZIP reading or writing */ + +/* Clears a mz_zip_archive struct to all zeros. */ +/* Important: This must be done before passing the struct to any mz_zip functions. */ +void mz_zip_zero_struct(mz_zip_archive *pZip); + +mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip); +mz_zip_type mz_zip_get_type(mz_zip_archive *pZip); + +/* Returns the total number of files in the archive. */ +mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip); + +mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip); +mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip); +MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip); + +/* Reads n bytes of raw archive data, starting at file offset file_ofs, to pBuf. */ +size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n); + +/* Attempts to locates a file in the archive's central directory. */ +/* Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH */ +/* Returns -1 if the file cannot be found. */ +int mz_zip_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); +/* Returns MZ_FALSE if the file cannot be found. */ +mz_bool mz_zip_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *pIndex); + +/* All mz_zip funcs set the m_last_error field in the mz_zip_archive struct. These functions retrieve/manipulate this field. */ +/* Note that the m_last_error functionality is not thread safe. */ +mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num); +mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip); +mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip); +mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip); +const char *mz_zip_get_error_string(mz_zip_error mz_err); + +/* MZ_TRUE if the archive file entry is a directory entry. */ +mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index); + +/* MZ_TRUE if the file is encrypted/strong encrypted. */ +mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index); + +/* MZ_TRUE if the compression method is supported, and the file is not encrypted, and the file is not a compressed patch file. */ +mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index); + +/* Retrieves the filename of an archive file entry. */ +/* Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename. */ +mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size); + +/* Attempts to locates a file in the archive's central directory. */ +/* Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH */ +/* Returns -1 if the file cannot be found. */ +int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); +int mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *file_index); + +/* Returns detailed information about an archive file entry. */ +mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat); + +/* MZ_TRUE if the file is in zip64 format. */ +/* A file is considered zip64 if it contained a zip64 end of central directory marker, or if it contained any zip64 extended file information fields in the central directory. */ +mz_bool mz_zip_is_zip64(mz_zip_archive *pZip); + +/* Returns the total central directory size in bytes. */ +/* The current max supported size is <= MZ_UINT32_MAX. */ +size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip); + +/* Extracts a archive file to a memory buffer using no memory allocation. */ +/* There must be at least enough room on the stack to store the inflator's state (~34KB or so). */ +mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); +mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); + +/* Extracts a archive file to a memory buffer. */ +mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags); +mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags); + +/* Extracts a archive file to a dynamically allocated heap buffer. */ +/* The memory will be allocated via the mz_zip_archive's alloc/realloc functions. */ +/* Returns NULL and sets the last error on failure. */ +void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags); +void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags); + +/* Extracts a archive file using a callback function to output the file's data. */ +mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); +mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); + +#ifndef MINIZ_NO_STDIO +/* Extracts a archive file to a disk file and sets its last accessed and modified times. */ +/* This function only extracts files, not archive directory records. */ +mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags); +mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags); + +/* Extracts a archive file starting at the current position in the destination FILE stream. */ +mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index, MZ_FILE *File, mz_uint flags); +mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags); +#endif + +#if 0 +/* TODO */ + typedef void *mz_zip_streaming_extract_state_ptr; + mz_zip_streaming_extract_state_ptr mz_zip_streaming_extract_begin(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags); + uint64_t mz_zip_streaming_extract_get_size(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); + uint64_t mz_zip_streaming_extract_get_cur_ofs(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); + mz_bool mz_zip_streaming_extract_seek(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, uint64_t new_ofs); + size_t mz_zip_streaming_extract_read(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, void *pBuf, size_t buf_size); + mz_bool mz_zip_streaming_extract_end(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); +#endif + +/* This function compares the archive's local headers, the optional local zip64 extended information block, and the optional descriptor following the compressed data vs. the data in the central directory. */ +/* It also validates that each file can be successfully uncompressed unless the MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY is specified. */ +mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags); + +/* Validates an entire archive by calling mz_zip_validate_file() on each file. */ +mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags); + +/* Misc utils/helpers, valid for ZIP reading or writing */ +mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr); +mz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zip_error *pErr); + +/* Universal end function - calls either mz_zip_reader_end() or mz_zip_writer_end(). */ +mz_bool mz_zip_end(mz_zip_archive *pZip); + +/* -------- ZIP writing */ + +#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS + +/* Inits a ZIP archive writer. */ +mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size); +mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_uint flags); +mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size); +mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size, mz_uint flags); + +#ifndef MINIZ_NO_STDIO +mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning); +mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning, mz_uint flags); +mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags); +#endif + +/* Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive. */ +/* For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called. */ +/* For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it). */ +/* Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL. */ +/* Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before */ +/* the archive is finalized the file's central directory will be hosed. */ +mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename); +mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags); + +/* Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive. */ +/* To add a directory entry, call this method with an archive name ending in a forwardslash with an empty buffer. */ +/* level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. */ +mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags); + +/* Like mz_zip_writer_add_mem(), except you can specify a file comment field, and optionally supply the function with already compressed data. */ +/* uncomp_size/uncomp_crc32 are only used if the MZ_ZIP_FLAG_COMPRESSED_DATA flag is specified. */ +mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, + mz_uint64 uncomp_size, mz_uint32 uncomp_crc32); + +mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, + mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified, const char *user_extra_data_local, mz_uint user_extra_data_local_len, + const char *user_extra_data_central, mz_uint user_extra_data_central_len); + +#ifndef MINIZ_NO_STDIO +/* Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive. */ +/* level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. */ +mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); + +/* Like mz_zip_writer_add_file(), except the file data is read from the specified FILE stream. */ +mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 size_to_add, + const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, const char *user_extra_data_local, mz_uint user_extra_data_local_len, + const char *user_extra_data_central, mz_uint user_extra_data_central_len); +#endif + +/* Adds a file to an archive by fully cloning the data from another archive. */ +/* This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data (it may add or modify the zip64 local header extra data field), and the optional descriptor following the compressed data. */ +mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint src_file_index); + +/* Finalizes the archive by writing the central directory records followed by the end of central directory record. */ +/* After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end(). */ +/* An archive must be manually finalized by calling this function for it to be valid. */ +mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip); + +/* Finalizes a heap archive, returning a poiner to the heap block and its size. */ +/* The heap block will be allocated using the mz_zip_archive's alloc/realloc callbacks. */ +mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf, size_t *pSize); + +/* Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used. */ +/* Note for the archive to be valid, it *must* have been finalized before ending (this function will not do it for you). */ +mz_bool mz_zip_writer_end(mz_zip_archive *pZip); + +/* -------- Misc. high-level helper functions: */ + +/* mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive. */ +/* Note this is NOT a fully safe operation. If it crashes or dies in some way your archive can be left in a screwed up state (without a central directory). */ +/* level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. */ +/* TODO: Perhaps add an option to leave the existing central dir in place in case the add dies? We could then truncate the file (so the old central dir would be at the end) if something goes wrong. */ +mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); +mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_zip_error *pErr); + +/* Reads a single file from an archive into a heap block. */ +/* If pComment is not NULL, only the file with the specified comment will be extracted. */ +/* Returns NULL on failure. */ +void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags); +void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const char *pArchive_name, const char *pComment, size_t *pSize, mz_uint flags, mz_zip_error *pErr); + +#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS */ + +#ifdef __cplusplus +} +#endif From c2a8fb2485c18a78749b895719c1946f526b3f87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Thu, 23 Feb 2017 13:03:47 +0100 Subject: [PATCH 092/699] type cleanup in miniz --- src/miniz/miniz.h | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/miniz/miniz.h b/src/miniz/miniz.h index daa6423c08b..45659d8cf1a 100644 --- a/src/miniz/miniz.h +++ b/src/miniz/miniz.h @@ -176,7 +176,7 @@ -/* Defines to completely disable specific portions of miniz.c: +/* Defines to completely disable specific portions of miniz.c: If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl. */ /* Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O. */ @@ -199,7 +199,7 @@ /* Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib. */ /*#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES */ -/* Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc. +/* Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc. Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work. */ @@ -523,19 +523,20 @@ typedef void *const voidpc; #include #include #include +#include /* ------------------- Types and macros */ -typedef unsigned char mz_uint8; -typedef signed short mz_int16; -typedef unsigned short mz_uint16; -typedef unsigned int mz_uint32; +typedef uint8_t mz_uint8; +typedef int16_t mz_int16; +typedef uint16_t mz_uint16; +typedef uint32_t mz_uint32; typedef unsigned int mz_uint; typedef int64_t mz_int64; typedef uint64_t mz_uint64; -typedef int mz_bool; +typedef bool mz_bool; -#define MZ_FALSE (0) -#define MZ_TRUE (1) +#define MZ_FALSE false +#define MZ_TRUE true /* Works around MSVC's spammy "warning C4127: conditional expression is constant" message. */ #ifdef _MSC_VER @@ -1195,7 +1196,7 @@ mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, cha /* Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH */ /* Returns -1 if the file cannot be found. */ int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); -int mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *file_index); +mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *file_index); /* Returns detailed information about an archive file entry. */ mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat); From 1dd43f6344ea9042aeb4c472f9fbb697a5aa65b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Tue, 14 Feb 2017 12:08:07 +0100 Subject: [PATCH 093/699] update Makefiles / remove all references to libzip/zlib --- src/Makefile | 30 ++------------------ src/cbmc/Makefile | 6 ++-- src/cegis/Makefile | 6 ++-- src/clobber/Makefile | 3 +- src/config.inc | 2 -- src/goto-analyzer/Makefile | 6 ++-- src/goto-cc/Makefile | 6 ++-- src/goto-diff/Makefile | 6 ++-- src/goto-instrument/Makefile | 6 ++-- src/java_bytecode/Makefile | 5 ---- src/java_bytecode/java_bytecode_language.cpp | 6 ---- src/java_bytecode/java_class_loader.cpp | 5 ---- src/miniz/Makefile | 7 ++--- src/symex/Makefile | 6 ++-- 14 files changed, 21 insertions(+), 79 deletions(-) diff --git a/src/Makefile b/src/Makefile index e4c62f33eed..7562863742e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,7 +2,7 @@ DIRS = ansi-c big-int cbmc cpp goto-cc goto-instrument goto-programs \ goto-symex langapi pointer-analysis solvers util linking xmllang \ assembler analyses java_bytecode path-symex musketeer \ json cegis goto-analyzer jsil symex goto-diff clobber \ - memory-models + memory-models miniz all: cbmc.dir goto-cc.dir goto-instrument.dir symex.dir goto-analyzer.dir goto-diff.dir @@ -20,7 +20,7 @@ cpp.dir: ansi-c.dir linking.dir languages: util.dir langapi.dir \ cpp.dir ansi-c.dir xmllang.dir assembler.dir java_bytecode.dir \ - jsil.dir + jsil.dir miniz.dir goto-instrument.dir: languages goto-programs.dir pointer-analysis.dir \ goto-symex.dir linking.dir analyses.dir solvers.dir \ @@ -84,30 +84,6 @@ glucose-download: @(cd ../glucose-syrup; patch -p1 < ../scripts/glucose-syrup-patch) @rm glucose-syrup.tgz -zlib-download: - @echo "Downloading zlib 1.2.11" - @lwp-download http://zlib.net/zlib-1.2.11.tar.gz - @tar xfz zlib-1.2.11.tar.gz - @rm -Rf ../zlib - @mv zlib-1.2.11 ../zlib - @rm zlib-1.2.11.tar.gz - -libzip-download: - @echo "Downloading libzip 1.1.2" - # The below wants SSL - #@lwp-download http://www.nih.at/libzip/libzip-1.1.2.tar.gz - @lwp-download http://http.debian.net/debian/pool/main/libz/libzip/libzip_1.1.2.orig.tar.gz - @tar xfz libzip_1.1.2.orig.tar.gz - @rm -Rf ../libzip - @mv libzip-1.1.2 ../libzip - @rm libzip_1.1.2.orig.tar.gz - -libzip-build: - @echo "Building zlib" - @(cd ../zlib; ./configure; make) - @echo "Building libzip" - @(cd ../libzip; BASE=`pwd`; ./configure --with-zlib=$(BASE)/zlib ; make) - cprover-jar-build: @echo "Building org.cprover.jar" @(cd java_bytecode/library/; \ @@ -116,4 +92,4 @@ cprover-jar-build: cd target; jar cf org.cprover.jar `find . -name "*.class"`; \ mv org.cprover.jar ../../../) -.PHONY: minisat2-download glucose-download zlib-download libzip-download libzip-build cprover-jar-build +.PHONY: minisat2-download glucose-download cprover-jar-build diff --git a/src/cbmc/Makefile b/src/cbmc/Makefile index 8bf055fe3b2..4fdb5338e41 100644 --- a/src/cbmc/Makefile +++ b/src/cbmc/Makefile @@ -28,7 +28,8 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \ ../assembler/assembler$(LIBEXT) \ ../solvers/solvers$(LIBEXT) \ ../util/util$(LIBEXT) \ - ../json/json$(LIBEXT) + ../json/json$(LIBEXT) \ + ../miniz/miniz$(OBJEXT) INCLUDES= -I .. @@ -49,9 +50,6 @@ endif ifneq ($(wildcard ../java_bytecode/Makefile),) OBJ += ../java_bytecode/java_bytecode$(LIBEXT) CP_CXXFLAGS += -DHAVE_JAVA_BYTECODE - ifneq ($(wildcard $(LIBZIPINC)),) - LIBS += $(LIBZIPLIB) - endif endif ifneq ($(wildcard ../jsil/Makefile),) diff --git a/src/cegis/Makefile b/src/cegis/Makefile index a126776bd03..be519a9e8a1 100644 --- a/src/cegis/Makefile +++ b/src/cegis/Makefile @@ -116,7 +116,8 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \ ../cbmc/cbmc_dimacs$(OBJEXT) ../cbmc/all_properties$(OBJEXT) \ ../cbmc/fault_localization$(OBJEXT) \ ../cbmc/symex_coverage$(OBJEXT) \ - ../json/json$(LIBEXT) + ../json/json$(LIBEXT) \ + ../miniz/miniz$(OBJEXT) INCLUDES= -I .. @@ -138,9 +139,6 @@ all: cegis$(EXEEXT) ifneq ($(wildcard ../java_bytecode/Makefile),) OBJ += ../java_bytecode/java_bytecode$(LIBEXT) CP_CXXFLAGS += -DHAVE_JAVA_BYTECODE - ifneq ($(wildcard $(LIBZIPINC)),) - LIBS += $(LIBZIPLIB) - endif endif ############################################################################### diff --git a/src/clobber/Makefile b/src/clobber/Makefile index f9c76dda397..ee77d22e33a 100644 --- a/src/clobber/Makefile +++ b/src/clobber/Makefile @@ -15,7 +15,8 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \ ../goto-symex/rewrite_union$(OBJEXT) \ ../pointer-analysis/dereference$(OBJEXT) \ ../goto-instrument/dump_c$(OBJEXT) \ - ../goto-instrument/goto_program2code$(OBJEXT) + ../goto-instrument/goto_program2code$(OBJEXT) \ + ../miniz/miniz$(OBJEXT) INCLUDES= -I .. diff --git a/src/config.inc b/src/config.inc index 2553a2062d8..e1c1266f683 100644 --- a/src/config.inc +++ b/src/config.inc @@ -24,8 +24,6 @@ BUILD_ENV = AUTO MINISAT2 = ../../minisat-2.2.1 #GLUCOSE = ../../glucose-syrup #SMVSAT = -LIBZIPLIB = ../../libzip/lib/.libs/libzip.a ../../zlib/libz.a -LIBZIPINC = ../../libzip/lib # Signing identity for MacOS Gatekeeper diff --git a/src/goto-analyzer/Makefile b/src/goto-analyzer/Makefile index bfeac69abba..b27b514bf88 100644 --- a/src/goto-analyzer/Makefile +++ b/src/goto-analyzer/Makefile @@ -12,7 +12,8 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \ ../langapi/langapi$(LIBEXT) \ ../json/json$(LIBEXT) \ ../assembler/assembler$(LIBEXT) \ - ../util/util$(LIBEXT) + ../util/util$(LIBEXT) \ + ../miniz/miniz$(OBJEXT) INCLUDES= -I .. @@ -28,9 +29,6 @@ all: goto-analyzer$(EXEEXT) ifneq ($(wildcard ../java_bytecode/Makefile),) OBJ += ../java_bytecode/java_bytecode$(LIBEXT) CP_CXXFLAGS += -DHAVE_JAVA_BYTECODE - ifneq ($(wildcard $(LIBZIPINC)),) - LIBS += $(LIBZIPLIB) - endif endif ifneq ($(wildcard ../jsil/Makefile),) diff --git a/src/goto-cc/Makefile b/src/goto-cc/Makefile index 727a010fb1d..04261db95f0 100644 --- a/src/goto-cc/Makefile +++ b/src/goto-cc/Makefile @@ -13,7 +13,8 @@ OBJ += ../big-int/big-int$(LIBEXT) \ ../cpp/cpp$(LIBEXT) \ ../xmllang/xmllang$(LIBEXT) \ ../assembler/assembler$(LIBEXT) \ - ../langapi/langapi$(LIBEXT) + ../langapi/langapi$(LIBEXT) \ + ../miniz/miniz$(OBJEXT) INCLUDES= -I .. @@ -31,9 +32,6 @@ all: goto-cc$(EXEEXT) ifneq ($(wildcard ../java_bytecode/Makefile),) OBJ += ../java_bytecode/java_bytecode$(LIBEXT) - ifneq ($(wildcard $(LIBZIPINC)),) - LIBS += $(LIBZIPLIB) - endif endif ifneq ($(wildcard ../jsil/Makefile),) diff --git a/src/goto-diff/Makefile b/src/goto-diff/Makefile index 6f9dd1a893a..c003d0c96b0 100644 --- a/src/goto-diff/Makefile +++ b/src/goto-diff/Makefile @@ -13,7 +13,8 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \ ../langapi/langapi$(LIBEXT) \ ../xmllang/xmllang$(LIBEXT) \ ../util/util$(LIBEXT) \ - ../solvers/solvers$(LIBEXT) + ../solvers/solvers$(LIBEXT) \ + ../miniz/miniz$(OBJEXT) INCLUDES= -I .. @@ -29,9 +30,6 @@ all: goto-diff$(EXEEXT) ifneq ($(wildcard ../java_bytecode/Makefile),) OBJ += ../java_bytecode/java_bytecode$(LIBEXT) CP_CXXFLAGS += -DHAVE_JAVA_BYTECODE - ifneq ($(wildcard $(LIBZIPINC)),) - LIBS += $(LIBZIPLIB) - endif endif ifneq ($(wildcard ../specc/Makefile),) diff --git a/src/goto-instrument/Makefile b/src/goto-instrument/Makefile index df45e7612fe..571bdf90eb9 100644 --- a/src/goto-instrument/Makefile +++ b/src/goto-instrument/Makefile @@ -38,7 +38,8 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \ ../xmllang/xmllang$(LIBEXT) \ ../util/util$(LIBEXT) \ ../json/json$(LIBEXT) \ - ../solvers/solvers$(LIBEXT) + ../solvers/solvers$(LIBEXT) \ + ../miniz/miniz$(OBJEXT) INCLUDES= -I .. @@ -54,9 +55,6 @@ all: goto-instrument$(EXEEXT) ifneq ($(wildcard ../java_bytecode/Makefile),) OBJ += ../java_bytecode/java_bytecode$(LIBEXT) CP_CXXFLAGS += -DHAVE_JAVA_BYTECODE - ifneq ($(wildcard $(LIBZIPINC)),) - LIBS += $(LIBZIPLIB) - endif endif ifneq ($(LIB_GLPK),) diff --git a/src/java_bytecode/Makefile b/src/java_bytecode/Makefile index e27bc3e038d..20958a3ede3 100644 --- a/src/java_bytecode/Makefile +++ b/src/java_bytecode/Makefile @@ -15,11 +15,6 @@ include ../common CLEANFILES = java_bytecode$(LIBEXT) -ifneq ($(wildcard $(LIBZIPINC)),) - INCLUDES += -I $(LIBZIPINC) - CP_CXXFLAGS += -DHAVE_LIBZIP -endif - all: java_bytecode$(LIBEXT) ############################################################################### diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index eaae4b50a77..37ed835eca0 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -138,7 +138,6 @@ bool java_bytecode_languaget::parse( } else if(has_suffix(path, ".jar")) { - #ifdef HAVE_LIBZIP if(config.java.main_class.empty()) { // Does it have a main class set in the manifest? @@ -162,11 +161,6 @@ bool java_bytecode_languaget::parse( } else java_class_loader.add_jar_file(path); - - #else - error() << "No support for reading JAR files" << eom; - return true; - #endif } else assert(false); diff --git a/src/java_bytecode/java_class_loader.cpp b/src/java_bytecode/java_class_loader.cpp index 541faf6828d..dc4330aa00c 100644 --- a/src/java_bytecode/java_class_loader.cpp +++ b/src/java_bytecode/java_class_loader.cpp @@ -212,11 +212,6 @@ void java_class_loadert::read_jar_file(const irep_idt &file) if(jar_map.find(file)!=jar_map.end()) return; - #ifndef HAVE_LIBZIP - error() << "no support for reading JAR files configured" << eom; - return; - #endif - jar_filet &jar_file=jar_pool(id2string(file)); if(!jar_file) diff --git a/src/miniz/Makefile b/src/miniz/Makefile index f2367695802..324c9821b91 100644 --- a/src/miniz/Makefile +++ b/src/miniz/Makefile @@ -5,11 +5,8 @@ INCLUDES= -I .. include ../config.inc include ../common -CLEANFILES = miniz$(LIBEXT) +CLEANFILES = miniz$(OBJEXT) -all: miniz$(LIBEXT) +all: miniz$(OBJEXT) ############################################################################### - -miniz$(LIBEXT): $(OBJ) - $(LINKLIB) diff --git a/src/symex/Makefile b/src/symex/Makefile index e3a9c677b78..e152b2461bf 100644 --- a/src/symex/Makefile +++ b/src/symex/Makefile @@ -17,7 +17,8 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \ ../pointer-analysis/dereference$(OBJEXT) \ ../goto-instrument/cover$(OBJEXT) \ ../json/json$(LIBEXT) \ - ../path-symex/path-symex$(LIBEXT) + ../path-symex/path-symex$(LIBEXT) \ + ../miniz/miniz$(OBJEXT) INCLUDES= -I .. @@ -38,9 +39,6 @@ endif ifneq ($(wildcard ../java_bytecode/Makefile),) OBJ += ../java_bytecode/java_bytecode$(LIBEXT) CP_CXXFLAGS += -DHAVE_JAVA_BYTECODE - ifneq ($(wildcard $(LIBZIPINC)),) - LIBS += $(LIBZIPLIB) - endif endif ifneq ($(wildcard ../specc/Makefile),) From 8e3f681257ee906f7dafd24c52e741549dad3b2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Tue, 14 Feb 2017 11:53:34 +0100 Subject: [PATCH 094/699] regression test with multiple JARs/classpath --- regression/cbmc-java/jar-file3/A.jar | Bin 0 -> 721 bytes regression/cbmc-java/jar-file3/B.jar | Bin 0 -> 721 bytes regression/cbmc-java/jar-file3/C.jar | Bin 0 -> 934 bytes regression/cbmc-java/jar-file3/jarfile3.class | Bin 0 -> 709 bytes regression/cbmc-java/jar-file3/jarfile3.java | 19 ++++++++++++++++++ regression/cbmc-java/jar-file3/test.desc | 8 ++++++++ 6 files changed, 27 insertions(+) create mode 100644 regression/cbmc-java/jar-file3/A.jar create mode 100644 regression/cbmc-java/jar-file3/B.jar create mode 100644 regression/cbmc-java/jar-file3/C.jar create mode 100644 regression/cbmc-java/jar-file3/jarfile3.class create mode 100644 regression/cbmc-java/jar-file3/jarfile3.java create mode 100644 regression/cbmc-java/jar-file3/test.desc diff --git a/regression/cbmc-java/jar-file3/A.jar b/regression/cbmc-java/jar-file3/A.jar new file mode 100644 index 0000000000000000000000000000000000000000..e721e6f32f945341ca9aafca44a794bb16cfeb02 GIT binary patch literal 721 zcmWIWW@Zs#;Nak3$Pf4PVn70%3@i-3t|5-Po_=on|4uP5Ff#;rvvYt{FhP|C;M6Pv zQ~}rQ>*(j{<{BKL=j-;__snS@Z(Y5MyxzK6=gyqp9At3C_`%a6JuhD!Pv48Bt5`TA zUPvC1mXg%U_#v*U_I!z!#dC4dC*rEp7_Mf2D*9N&2zG^l;4&o_pdGG2jBrIdnim9s zvRR2mX_+~x#ww0_$vKI|#jgIo-iI9oYA>t!?p9O#8lCUNZ`vBR!Q6F1Q-DTQz@Ge9 ztE3-^O$zxFE!Xwnp!|b=p>*bhhozrA-fM1bzd!yygPO&wL#{dx7N&33mAAJ0#`)#k z48dDhyY+rAXE8jV@^MLVY1z5E+_@#Co*eA|-%e(4vW~UWax%H@c6Uu&aOj=WCeQnJ zM6c^=-F0mnhxA#E$@xYO>~|TM*coqqsFg9=oA_n@4?Z^oV>i*uG1Hc6ac>E6$vE ze0%0HG0}sPH<+z@1&;seJ8r*CB8U6P#@HjG)}OZV_A!P#r$zWp;kmxxiSXJZv4?-I z=u~tM?3bNZH7EDlG{JALIO}_I-!%OL2i}6vmH++&gC>v>6nKnGA`GZ002aNV6o3lg zQ3^^A=vtBE1Qh=WU<+izwIZbkWD`JfhwLy=+#$eWAQL?%1H4(;Kq{Dla5snnb~gZw CHqIXa literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/jar-file3/B.jar b/regression/cbmc-java/jar-file3/B.jar new file mode 100644 index 0000000000000000000000000000000000000000..d381e413e74f2aa5d1f92381ec7fe608679b7e81 GIT binary patch literal 721 zcmWIWW@Zs#;Nak3C=U1YVn70%3@i-3t|5-Po_=on|4uP5Ff#;rvvYt{FhP|C;M6Pv zQ~}rQ>*(j{<{BKL=j-;__snS@Z(Y5MyxzK6=gyqp9At3C_`%a6JuhD!Pv48Bt5`TA zUPvC1mXg%U_#v*U_I!z!#dC4dC*rEp7_Mf2D*9N&2zG^l;4&o_pdGG2jBrIdnim9s zvRR2mX_+~x#wt#F$vKI|#jgIo-iI9oYA-Lln|61`kH3Y&RVy^NG~E;77i)34*!-wA zIQ*_aut(6x{7Q``_WA~UuQ|Ld{P{Ebzu!Ca=TBWNv&G?s{QMJL*roMui`)>qp?twQ z+3Q7^{^b@9qQIepCtu>P_P*wY%PRA_JeQrmG^OPP=kb~6 z<{#hgne|L`p=|;C7b(TQA9MNs-$>e^E8v)Or~%rTH#=kQTIYU6gN z-;34QWKwO#biP_fuh(^cb4~c4MDz{Dzl@+Lv^lv+>OU}O0vSPp$H*kYfSLke(F;le zr~n?Np!9&Q6**2o@s9wuKqg!(Qffdp0Tg%04g*(j{<{BKL=j-;__snS@Z(Y5MyxzK6=gyqp9At3C_`%a6JuhD!Pv48Bt5`TA zUPvC1mXg%U_#v*U_I!z!#dC4dC*rEp7_Mf2D*9N&2zG^l;4&o_pdGG2jBv&AXjCuo z0cEoii_$W4QjPVJa}tY-eS>2Cg&jp~H{UJWEkD(1={5c%UKd##XPubMqPxOV*iOzs z?ZdWQ_RU-K&c3uq&??>SSR&rJv ziT4i4va`JsduL@3xcy<$LA6U8HoRESQ90Yd{JYGZ_WVRohaAp|w;GeOss)a0?BU$X zqQ$#6(9@#lQF@|G3EQUQXC^u%D)$^p308QnzgNg$d%LZs!B%0nqWmx0l&^aGs(qi~ zxqq$Y(q@$x`)=~yTdKKhiDTmn2TX z?49N|O)EjJ&w%(^$lVXOM%fRp!H`EL8T6;>I$ulW4QyGAB(U1oJpk-#p=bDQs+ zEfkIUd^%kq-b66;T&u{H$5L6(uk`Df?zEFUY@uSi-MVdM^PhX+B7OmpmaVCEP1bH7 zKk$58|Nq4+%{ix6h#3Y=)cQ1M{efd5bEiJM{7`N2YZqII`Y-o)BtCqm^Z(3R?&Ggl z>Lyej`^)#fWzzh_XZsc!SXvaX=RbA$!#pmvXP3U@W;IH&MHjAIYpl2Rs68lU{uE0H zyurx8a1@w41H2iTL>N#LHZ0YG5;iJ;r&LffN7ss+)IiA^0c?RxxK^Y@j%)%bNg_K8 clq3=0Fp!CwKm)v4*+BBlK)4e~UkAGy09`dfUjP6A literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/jar-file3/jarfile3.class b/regression/cbmc-java/jar-file3/jarfile3.class new file mode 100644 index 0000000000000000000000000000000000000000..ececc4cc3057d71a26d614fed6c32b64d2261195 GIT binary patch literal 709 zcmYjPT~8B16g{)ucDo;yLZQ|V#7fZxfttvh1TCmZ6Fwd=Ch)dx2eY+q&Ft3bU*W|^ zpH(7>P4wOWr18w^QXY2Z&bepqIrr}T`t$t*qD`b> zVaY)e3pQaM?mD;!-@>wh*cR~GQ6$yQAc$ib6KV-m8v3A;a2Ul;!#L;+WRIC+fx>1O zg~^sc&R>2hVD1ciQebK~jO704O-HI1noRBqlYU!sN{30%eZ3dFO;dD9g963P?%;nZ z=WsYuUHLrJ7fby>oiKX1-Vfdd9x9j>a5Avb(#XnXWZT0uW<1=-sz6O&Y7Tnodff+LLjpWbZ>m54>t}e>{e9 zM0##-3{waB{Vyn-qOy7h%lrs;jN;Kb?4SS8wKF)EQ7vMmB30xWUxAG&IxEAc!!1VF zh$h>;!i_n;nVT1mH&ScB^o;ur-YF$N!OVR{VNy7AuM6d2cuxcs=TqHV)B-gO Mw&GG-XIyHFzoIF8asU7T literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/jar-file3/jarfile3.java b/regression/cbmc-java/jar-file3/jarfile3.java new file mode 100644 index 00000000000..c9c0cff46d1 --- /dev/null +++ b/regression/cbmc-java/jar-file3/jarfile3.java @@ -0,0 +1,19 @@ +public class jarfile3 +{ + public class A + { + int x=1; + } + public class B + { + int x=1; + } + + void f(int i) + { + A a=new A(); + B b=new B(); + assert(a.x==1); + assert(b.x==1); + } +} diff --git a/regression/cbmc-java/jar-file3/test.desc b/regression/cbmc-java/jar-file3/test.desc new file mode 100644 index 00000000000..8d3b495e1c6 --- /dev/null +++ b/regression/cbmc-java/jar-file3/test.desc @@ -0,0 +1,8 @@ +CORE +C.jar +--function jarfile3.f -classpath A.jar:B.jar +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL +-- +^warning: ignoring From 85889e9bdf187163e04674228bcb0992b8c68b55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Thu, 23 Feb 2017 14:05:13 +0100 Subject: [PATCH 095/699] disable unaligned load/store for g++ --- src/miniz/miniz.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/miniz/miniz.h b/src/miniz/miniz.h index 45659d8cf1a..6353d3782b2 100644 --- a/src/miniz/miniz.h +++ b/src/miniz/miniz.h @@ -224,7 +224,7 @@ #define MINIZ_LITTLE_ENDIAN 1 #endif -#if MINIZ_X86_OR_X64_CPU +#if defined(MINIZ_X86_OR_X64_CPU) && !defined(__GNUG__) /* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. */ #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 #endif From c384ff74ef2cd4ff16ebf43ed79383408985415c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Thu, 23 Feb 2017 14:38:30 +0100 Subject: [PATCH 096/699] auto-fix cpplint errors with generated sed script --- src/miniz/miniz.cpp | 1870 +++++++++++++++++++++---------------------- src/miniz/miniz.h | 18 +- 2 files changed, 944 insertions(+), 944 deletions(-) diff --git a/src/miniz/miniz.cpp b/src/miniz/miniz.cpp index fa5c1903e83..4fff76e87d7 100644 --- a/src/miniz/miniz.cpp +++ b/src/miniz/miniz.cpp @@ -40,11 +40,11 @@ mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) { mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552; - if (!ptr) + if(!ptr) return MZ_ADLER32_INIT; - while (buf_len) + while(buf_len) { - for (i = 0; i + 7 < block_len; i += 8, ptr += 8) + for(i = 0; i + 7 < block_len; i += 8, ptr += 8) { s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; @@ -55,7 +55,7 @@ mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; } - for (; i < block_len; ++i) + for(; i < block_len; ++i) s1 += *ptr++, s2 += s1; s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; @@ -64,17 +64,17 @@ mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) return (s2 << 16) + s1; } -/* Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ */ +/* Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http:// www.geocities.com/malbrain/ */ #if 0 mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) { static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; mz_uint32 crcu32 = (mz_uint32)crc; - if (!ptr) + if(!ptr) return MZ_CRC32_INIT; crcu32 = ~crcu32; - while (buf_len--) + while(buf_len--) { mz_uint8 b = *ptr++; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; @@ -131,7 +131,7 @@ mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) mz_uint32 crc32 = (mz_uint32)crc ^ 0xFFFFFFFF; const mz_uint8 *pByte_buf = (const mz_uint8 *)ptr; - while (buf_len >= 4) + while(buf_len >= 4) { crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF]; crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF]; @@ -141,7 +141,7 @@ mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) buf_len -= 4; } - while (buf_len) + while(buf_len) { crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF]; ++pByte_buf; @@ -190,9 +190,9 @@ int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, tdefl_compressor *pComp; mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy); - if (!pStream) + if(!pStream) return MZ_STREAM_ERROR; - if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) + if((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) return MZ_PARAM_ERROR; pStream->data_type = 0; @@ -201,18 +201,18 @@ int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, pStream->reserved = 0; pStream->total_in = 0; pStream->total_out = 0; - if (!pStream->zalloc) + if(!pStream->zalloc) pStream->zalloc = miniz_def_alloc_func; - if (!pStream->zfree) + if(!pStream->zfree) pStream->zfree = miniz_def_free_func; pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor)); - if (!pComp) + if(!pComp) return MZ_MEM_ERROR; pStream->state = (struct mz_internal_state *)pComp; - if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) + if(tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) { mz_deflateEnd(pStream); return MZ_PARAM_ERROR; @@ -223,7 +223,7 @@ int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mz_deflateReset(mz_streamp pStream) { - if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) + if((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR; pStream->total_in = pStream->total_out = 0; tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL, ((tdefl_compressor *)pStream->state)->m_flags); @@ -236,20 +236,20 @@ int mz_deflate(mz_streamp pStream, int flush) mz_ulong orig_total_in, orig_total_out; int mz_status = MZ_OK; - if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) + if((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR; - if (!pStream->avail_out) + if(!pStream->avail_out) return MZ_BUF_ERROR; - if (flush == MZ_PARTIAL_FLUSH) + if(flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; - if (((tdefl_compressor *)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE) + if(((tdefl_compressor *)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE) return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR; orig_total_in = pStream->total_in; orig_total_out = pStream->total_out; - for (;;) + for(;;) { tdefl_status defl_status; in_bytes = pStream->avail_in; @@ -265,21 +265,21 @@ int mz_deflate(mz_streamp pStream, int flush) pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes; - if (defl_status < 0) + if(defl_status < 0) { mz_status = MZ_STREAM_ERROR; break; } - else if (defl_status == TDEFL_STATUS_DONE) + else if(defl_status == TDEFL_STATUS_DONE) { mz_status = MZ_STREAM_END; break; } - else if (!pStream->avail_out) + else if(!pStream->avail_out) break; - else if ((!pStream->avail_in) && (flush != MZ_FINISH)) + else if((!pStream->avail_in) && (flush != MZ_FINISH)) { - if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out)) + if((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out)) break; return MZ_BUF_ERROR; /* Can't make forward progress without some input. */ @@ -290,9 +290,9 @@ int mz_deflate(mz_streamp pStream, int flush) int mz_deflateEnd(mz_streamp pStream) { - if (!pStream) + if(!pStream) return MZ_STREAM_ERROR; - if (pStream->state) + if(pStream->state) { pStream->zfree(pStream->opaque, pStream->state); pStream->state = NULL; @@ -314,7 +314,7 @@ int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char memset(&stream, 0, sizeof(stream)); /* In case mz_ulong is 64-bits (argh I hate longs). */ - if ((source_len | *pDest_len) > 0xFFFFFFFFU) + if((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; stream.next_in = pSource; @@ -323,11 +323,11 @@ int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char stream.avail_out = (mz_uint32) * pDest_len; status = mz_deflateInit(&stream, level); - if (status != MZ_OK) + if(status != MZ_OK) return status; status = mz_deflate(&stream, MZ_FINISH); - if (status != MZ_STREAM_END) + if(status != MZ_STREAM_END) { mz_deflateEnd(&stream); return (status == MZ_OK) ? MZ_BUF_ERROR : status; @@ -359,9 +359,9 @@ typedef struct int mz_inflateInit2(mz_streamp pStream, int window_bits) { inflate_state *pDecomp; - if (!pStream) + if(!pStream) return MZ_STREAM_ERROR; - if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) + if((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR; pStream->data_type = 0; @@ -370,13 +370,13 @@ int mz_inflateInit2(mz_streamp pStream, int window_bits) pStream->total_in = 0; pStream->total_out = 0; pStream->reserved = 0; - if (!pStream->zalloc) + if(!pStream->zalloc) pStream->zalloc = miniz_def_alloc_func; - if (!pStream->zfree) + if(!pStream->zfree) pStream->zfree = miniz_def_free_func; pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state)); - if (!pDecomp) + if(!pDecomp) return MZ_MEM_ERROR; pStream->state = (struct mz_internal_state *)pDecomp; @@ -404,28 +404,28 @@ int mz_inflate(mz_streamp pStream, int flush) size_t in_bytes, out_bytes, orig_avail_in; tinfl_status status; - if ((!pStream) || (!pStream->state)) + if((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR; - if (flush == MZ_PARTIAL_FLUSH) + if(flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; - if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) + if((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; pState = (inflate_state *)pStream->state; - if (pState->m_window_bits > 0) + if(pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER; orig_avail_in = pStream->avail_in; first_call = pState->m_first_call; pState->m_first_call = 0; - if (pState->m_last_status < 0) + if(pState->m_last_status < 0) return MZ_DATA_ERROR; - if (pState->m_has_flushed && (flush != MZ_FINISH)) + if(pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; pState->m_has_flushed |= (flush == MZ_FINISH); - if ((flush == MZ_FINISH) && (first_call)) + if((flush == MZ_FINISH) && (first_call)) { /* MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. */ decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; @@ -441,9 +441,9 @@ int mz_inflate(mz_streamp pStream, int flush) pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes; - if (status < 0) + if(status < 0) return MZ_DATA_ERROR; - else if (status != TINFL_STATUS_DONE) + else if(status != TINFL_STATUS_DONE) { pState->m_last_status = TINFL_STATUS_FAILED; return MZ_BUF_ERROR; @@ -451,10 +451,10 @@ int mz_inflate(mz_streamp pStream, int flush) return MZ_STREAM_END; } /* flush != MZ_FINISH then we must assume there's more input. */ - if (flush != MZ_FINISH) + if(flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT; - if (pState->m_dict_avail) + if(pState->m_dict_avail) { n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); @@ -466,7 +466,7 @@ int mz_inflate(mz_streamp pStream, int flush) return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; } - for (;;) + for(;;) { in_bytes = pStream->avail_in; out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs; @@ -489,20 +489,20 @@ int mz_inflate(mz_streamp pStream, int flush) pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); - if (status < 0) + if(status < 0) return MZ_DATA_ERROR; /* Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). */ - else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in)) + else if((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in)) return MZ_BUF_ERROR; /* Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. */ - else if (flush == MZ_FINISH) + else if(flush == MZ_FINISH) { /* The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. */ - if (status == TINFL_STATUS_DONE) + if(status == TINFL_STATUS_DONE) return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END; /* status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. */ - else if (!pStream->avail_out) + else if(!pStream->avail_out) return MZ_BUF_ERROR; } - else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail)) + else if((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail)) break; } @@ -511,9 +511,9 @@ int mz_inflate(mz_streamp pStream, int flush) int mz_inflateEnd(mz_streamp pStream) { - if (!pStream) + if(!pStream) return MZ_STREAM_ERROR; - if (pStream->state) + if(pStream->state) { pStream->zfree(pStream->opaque, pStream->state); pStream->state = NULL; @@ -528,7 +528,7 @@ int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char memset(&stream, 0, sizeof(stream)); /* In case mz_ulong is 64-bits (argh I hate longs). */ - if ((source_len | *pDest_len) > 0xFFFFFFFFU) + if((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; stream.next_in = pSource; @@ -537,11 +537,11 @@ int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char stream.avail_out = (mz_uint32) * pDest_len; status = mz_inflateInit(&stream); - if (status != MZ_OK) + if(status != MZ_OK) return status; status = mz_inflate(&stream, MZ_FINISH); - if (status != MZ_STREAM_END) + if(status != MZ_STREAM_END) { mz_inflateEnd(&stream); return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status; @@ -563,8 +563,8 @@ const char *mz_error(int err) { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" } }; mz_uint i; - for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) - if (s_error_descs[i].m_err == err) + for(i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) + if(s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc; return NULL; } @@ -709,24 +709,24 @@ static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq *p mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1; MZ_CLEAR_OBJ(hist); - for (i = 0; i < num_syms; i++) + for(i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; } - while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) + while((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--; - for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) + for(pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) { const mz_uint32 *pHist = &hist[pass << 8]; mz_uint offsets[256], cur_ofs = 0; - for (i = 0; i < 256; i++) + for(i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; } - for (i = 0; i < num_syms; i++) + for(i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i]; { tdefl_sym_freq *t = pCur_syms; @@ -741,9 +741,9 @@ static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq *p static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) { int root, leaf, next, avbl, used, dpth; - if (n == 0) + if(n == 0) return; - else if (n == 1) + else if(n == 1) { A[0].m_key = 1; return; @@ -751,16 +751,16 @@ static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) A[0].m_key += A[1].m_key; root = 0; leaf = 2; - for (next = 1; next < n - 1; next++) + for(next = 1; next < n - 1; next++) { - if (leaf >= n || A[root].m_key < A[leaf].m_key) + if(leaf >= n || A[root].m_key < A[leaf].m_key) { A[next].m_key = A[root].m_key; A[root++].m_key = (mz_uint16)next; } else A[next].m_key = A[leaf++].m_key; - if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key)) + if(leaf >= n || (root < next && A[root].m_key < A[leaf].m_key)) { A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key); A[root++].m_key = (mz_uint16)next; @@ -769,20 +769,20 @@ static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key); } A[n - 2].m_key = 0; - for (next = n - 3; next >= 0; next--) + for(next = n - 3; next >= 0; next--) A[next].m_key = A[A[next].m_key].m_key + 1; avbl = 1; used = dpth = 0; root = n - 2; next = n - 1; - while (avbl > 0) + while(avbl > 0) { - while (root >= 0 && (int)A[root].m_key == dpth) + while(root >= 0 && (int)A[root].m_key == dpth) { used++; root--; } - while (avbl > used) + while(avbl > used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; @@ -802,17 +802,17 @@ static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_l { int i; mz_uint32 total = 0; - if (code_list_len <= 1) + if(code_list_len <= 1) return; - for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) + for(i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i]; - for (i = max_code_size; i > 0; i--) + for(i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i)); - while (total != (1UL << max_code_size)) + while(total != (1UL << max_code_size)) { pNum_codes[max_code_size]--; - for (i = max_code_size - 1; i > 0; i--) - if (pNum_codes[i]) + for(i = max_code_size - 1; i > 0; i--) + if(pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; @@ -827,9 +827,9 @@ static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; MZ_CLEAR_OBJ(num_codes); - if (static_table) + if(static_table) { - for (i = 0; i < table_len; i++) + for(i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++; } else @@ -837,8 +837,8 @@ static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms; int num_used_syms = 0; const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0]; - for (i = 0; i < table_len; i++) - if (pSym_count[i]) + for(i = 0; i < table_len; i++) + if(pSym_count[i]) { syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; syms0[num_used_syms++].m_sym_index = (mz_uint16)i; @@ -847,29 +847,29 @@ static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms); - for (i = 0; i < num_used_syms; i++) + for(i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++; tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit); MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]); - for (i = 1, j = num_used_syms; i <= code_size_limit; i++) - for (l = num_codes[i]; l > 0; l--) + for(i = 1, j = num_used_syms; i <= code_size_limit; i++) + for(l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i); } next_code[1] = 0; - for (j = 0, i = 2; i <= code_size_limit; i++) + for(j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1); - for (i = 0; i < table_len; i++) + for(i = 0; i < table_len; i++) { mz_uint rev_code = 0, code, code_size; - if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) + if((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue; code = next_code[code_size]++; - for (l = code_size; l > 0; l--, code >>= 1) + for(l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1); d->m_huff_codes[table_num][i] = (mz_uint16)rev_code; } @@ -883,9 +883,9 @@ static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int MZ_ASSERT(bits <= ((1U << len) - 1U)); \ d->m_bit_buffer |= (bits << d->m_bits_in); \ d->m_bits_in += len; \ - while (d->m_bits_in >= 8) \ + while(d->m_bits_in >= 8) \ { \ - if (d->m_pOutput_buf < d->m_pOutput_buf_end) \ + if(d->m_pOutput_buf < d->m_pOutput_buf_end) \ *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \ d->m_bit_buffer >>= 8; \ d->m_bits_in -= 8; \ @@ -895,12 +895,12 @@ static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int #define TDEFL_RLE_PREV_CODE_SIZE() \ { \ - if (rle_repeat_count) \ + if(rle_repeat_count) \ { \ - if (rle_repeat_count < 3) \ + if(rle_repeat_count < 3) \ { \ d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \ - while (rle_repeat_count--) \ + while(rle_repeat_count--) \ packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \ } \ else \ @@ -915,15 +915,15 @@ static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int #define TDEFL_RLE_ZERO_CODE_SIZE() \ { \ - if (rle_z_count) \ + if(rle_z_count) \ { \ - if (rle_z_count < 3) \ + if(rle_z_count < 3) \ { \ d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); \ - while (rle_z_count--) \ + while(rle_z_count--) \ packed_code_sizes[num_packed_code_sizes++] = 0; \ } \ - else if (rle_z_count <= 10) \ + else if(rle_z_count <= 10) \ { \ d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); \ packed_code_sizes[num_packed_code_sizes++] = 17; \ @@ -952,11 +952,11 @@ static void tdefl_start_dynamic_block(tdefl_compressor *d) tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE); tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE); - for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) - if (d->m_huff_code_sizes[0][num_lit_codes - 1]) + for(num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) + if(d->m_huff_code_sizes[0][num_lit_codes - 1]) break; - for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) - if (d->m_huff_code_sizes[1][num_dist_codes - 1]) + for(num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) + if(d->m_huff_code_sizes[1][num_dist_codes - 1]) break; memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes); @@ -967,13 +967,13 @@ static void tdefl_start_dynamic_block(tdefl_compressor *d) rle_repeat_count = 0; memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2); - for (i = 0; i < total_code_sizes_to_pack; i++) + for(i = 0; i < total_code_sizes_to_pack; i++) { mz_uint8 code_size = code_sizes_to_pack[i]; - if (!code_size) + if(!code_size) { TDEFL_RLE_PREV_CODE_SIZE(); - if (++rle_z_count == 138) + if(++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); } @@ -981,20 +981,20 @@ static void tdefl_start_dynamic_block(tdefl_compressor *d) else { TDEFL_RLE_ZERO_CODE_SIZE(); - if (code_size != prev_code_size) + if(code_size != prev_code_size) { TDEFL_RLE_PREV_CODE_SIZE(); d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); packed_code_sizes[num_packed_code_sizes++] = code_size; } - else if (++rle_repeat_count == 6) + else if(++rle_repeat_count == 6) { TDEFL_RLE_PREV_CODE_SIZE(); } } prev_code_size = code_size; } - if (rle_repeat_count) + if(rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } @@ -1010,20 +1010,20 @@ static void tdefl_start_dynamic_block(tdefl_compressor *d) TDEFL_PUT_BITS(num_lit_codes - 257, 5); TDEFL_PUT_BITS(num_dist_codes - 1, 5); - for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) - if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) + for(num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) + if(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break; num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4); - for (i = 0; (int)i < num_bit_lengths; i++) + for(i = 0; (int)i < num_bit_lengths; i++) TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3); - for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;) + for(packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;) { mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2); TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]); - if (code >= 16) + if(code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]); } } @@ -1033,13 +1033,13 @@ static void tdefl_start_static_block(tdefl_compressor *d) mz_uint i; mz_uint8 *p = &d->m_huff_code_sizes[0][0]; - for (i = 0; i <= 143; ++i) + for(i = 0; i <= 143; ++i) *p++ = 8; - for (; i <= 255; ++i) + for(; i <= 255; ++i) *p++ = 9; - for (; i <= 279; ++i) + for(; i <= 279; ++i) *p++ = 7; - for (; i <= 287; ++i) + for(; i <= 287; ++i) *p++ = 8; memset(d->m_huff_code_sizes[1], 5, 32); @@ -1069,12 +1069,12 @@ static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) } flags = 1; - for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1) + for(pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1) { - if (flags == 1) + if(flags == 1) flags = *pLZ_codes++ | 0x100; - if (flags & 1) + if(flags & 1) { mz_uint s0, s1, n0, n1, sym, num_extra_bits; mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); @@ -1102,14 +1102,14 @@ static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) MZ_ASSERT(d->m_huff_code_sizes[0][lit]); TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) + if(((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) { flags >>= 1; lit = *pLZ_codes++; MZ_ASSERT(d->m_huff_code_sizes[0][lit]); TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) + if(((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) { flags >>= 1; lit = *pLZ_codes++; @@ -1119,7 +1119,7 @@ static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) } } - if (pOutput_buf >= d->m_pOutput_buf_end) + if(pOutput_buf >= d->m_pOutput_buf_end) return MZ_FALSE; *(mz_uint64 *)pOutput_buf = bit_buffer; @@ -1134,7 +1134,7 @@ static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) d->m_bits_in = 0; d->m_bit_buffer = 0; - while (bits_in) + while(bits_in) { mz_uint32 n = MZ_MIN(bits_in, 16); TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n); @@ -1153,11 +1153,11 @@ static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) mz_uint8 *pLZ_codes; flags = 1; - for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1) + for(pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1) { - if (flags == 1) + if(flags == 1) flags = *pLZ_codes++ | 0x100; - if (flags & 1) + if(flags & 1) { mz_uint sym, num_extra_bits; mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); @@ -1167,7 +1167,7 @@ static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); - if (match_dist < 512) + if(match_dist < 512) { sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist]; @@ -1197,7 +1197,7 @@ static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) { - if (static_block) + if(static_block) tdefl_start_static_block(d); else tdefl_start_dynamic_block(d); @@ -1222,7 +1222,7 @@ static int tdefl_flush_block(tdefl_compressor *d, int flush) *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left); d->m_pLZ_code_buf -= (d->m_num_flags_left == 8); - if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) + if((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) { TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8); @@ -1234,50 +1234,50 @@ static int tdefl_flush_block(tdefl_compressor *d, int flush) saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in; - if (!use_raw_block) + if(!use_raw_block) comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48)); /* If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. */ - if (((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) && + if(((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) && ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size)) { mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; TDEFL_PUT_BITS(0, 2); - if (d->m_bits_in) + if(d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } - for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) + for(i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) { TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16); } - for (i = 0; i < d->m_total_lz_bytes; ++i) + for(i = 0; i < d->m_total_lz_bytes; ++i) { TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8); } } /* Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. */ - else if (!comp_block_succeeded) + else if(!comp_block_succeeded) { d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; tdefl_compress_block(d, MZ_TRUE); } - if (flush) + if(flush) { - if (flush == TDEFL_FINISH) + if(flush == TDEFL_FINISH) { - if (d->m_bits_in) + if(d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } - if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) + if(d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { mz_uint i, a = d->m_adler32; - for (i = 0; i < 4; i++) + for(i = 0; i < 4; i++) { TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); a <<= 8; @@ -1288,11 +1288,11 @@ static int tdefl_flush_block(tdefl_compressor *d, int flush) { mz_uint i, z = 0; TDEFL_PUT_BITS(0, 3); - if (d->m_bits_in) + if(d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } - for (i = 2; i; --i, z ^= 0xFFFF) + for(i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); } @@ -1311,20 +1311,20 @@ static int tdefl_flush_block(tdefl_compressor *d, int flush) d->m_total_lz_bytes = 0; d->m_block_index++; - if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) + if((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) { - if (d->m_pPut_buf_func) + if(d->m_pPut_buf_func) { *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; - if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user)) + if(!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user)) return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED); } - else if (pOutput_buf_start == d->m_output_buf) + else if(pOutput_buf_start == d->m_output_buf) { int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs)); memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy); d->m_out_buf_ofs += bytes_to_copy; - if ((n -= bytes_to_copy) != 0) + if((n -= bytes_to_copy) != 0) { d->m_output_flush_ofs = bytes_to_copy; d->m_output_flush_remaining = n; @@ -1348,46 +1348,46 @@ static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahe const mz_uint16 *s = (const mz_uint16 *)(d->m_dict + pos), *p, *q; mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s); MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); - if (max_match_len <= match_len) + if(max_match_len <= match_len) return; - for (;;) + for(;;) { - for (;;) + for(;;) { - if (--num_probes_left == 0) + if(--num_probes_left == 0) return; #define TDEFL_PROBE \ next_probe_pos = d->m_next[probe_pos]; \ - if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \ + if((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \ return; \ probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ - if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) \ + if(TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) \ break; TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; } - if (!dist) + if(!dist) break; q = (const mz_uint16 *)(d->m_dict + probe_pos); - if (TDEFL_READ_UNALIGNED_WORD(q) != s01) + if(TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; p = s; probe_len = 32; do { - } while ((TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && + } while((TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0)); - if (!probe_len) + if(!probe_len) { *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, (mz_uint)TDEFL_MAX_MATCH_LEN); break; } - else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q)) > match_len) + else if((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q)) > match_len) { *pMatch_dist = dist; - if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) + if((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break; c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]); } @@ -1401,36 +1401,36 @@ static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahe const mz_uint8 *s = d->m_dict + pos, *p, *q; mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1]; MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); - if (max_match_len <= match_len) + if(max_match_len <= match_len) return; - for (;;) + for(;;) { - for (;;) + for(;;) { - if (--num_probes_left == 0) + if(--num_probes_left == 0) return; #define TDEFL_PROBE \ next_probe_pos = d->m_next[probe_pos]; \ - if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \ + if((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \ return; \ probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ - if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) \ + if((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) \ break; TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; } - if (!dist) + if(!dist) break; p = s; q = d->m_dict + probe_pos; - for (probe_len = 0; probe_len < max_match_len; probe_len++) - if (*p++ != *q++) + for(probe_len = 0; probe_len < max_match_len; probe_len++) + if(*p++ != *q++) break; - if (probe_len > match_len) + if(probe_len > match_len) { *pMatch_dist = dist; - if ((*pMatch_len = match_len = probe_len) == max_match_len) + if((*pMatch_len = match_len = probe_len) == max_match_len) return; c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1]; @@ -1447,7 +1447,7 @@ static mz_bool tdefl_compress_fast(tdefl_compressor *d) mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags; mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; - while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) + while((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) { const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096; mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; @@ -1455,11 +1455,11 @@ static mz_bool tdefl_compress_fast(tdefl_compressor *d) d->m_src_buf_left -= num_bytes_to_process; lookahead_size += num_bytes_to_process; - while (num_bytes_to_process) + while(num_bytes_to_process) { mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process); memcpy(d->m_dict + dst_pos, d->m_pSrc, n); - if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) + if(dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos)); d->m_pSrc += n; dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK; @@ -1467,10 +1467,10 @@ static mz_bool tdefl_compress_fast(tdefl_compressor *d) } dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size); - if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) + if((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break; - while (lookahead_size >= 4) + while(lookahead_size >= 4) { mz_uint cur_match_dist, cur_match_len = 1; mz_uint8 *pCur_dict = d->m_dict + cur_pos; @@ -1479,20 +1479,20 @@ static mz_bool tdefl_compress_fast(tdefl_compressor *d) mz_uint probe_pos = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)lookahead_pos; - if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) + if(((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) { const mz_uint16 *p = (const mz_uint16 *)pCur_dict; const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos); mz_uint32 probe_len = 32; do { - } while ((TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && + } while((TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0)); cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q); - if (!probe_len) + if(!probe_len) cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0; - if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U))) + if((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U))) { cur_match_len = 1; *pLZ_code_buf++ = (mz_uint8)first_trigram; @@ -1527,7 +1527,7 @@ static mz_bool tdefl_compress_fast(tdefl_compressor *d) d->m_huff_count[0][(mz_uint8)first_trigram]++; } - if (--num_flags_left == 0) + if(--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; @@ -1540,7 +1540,7 @@ static mz_bool tdefl_compress_fast(tdefl_compressor *d) MZ_ASSERT(lookahead_size >= cur_match_len); lookahead_size -= cur_match_len; - if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) + if(pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) { int n; d->m_lookahead_pos = lookahead_pos; @@ -1550,7 +1550,7 @@ static mz_bool tdefl_compress_fast(tdefl_compressor *d) d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; - if ((n = tdefl_flush_block(d, 0)) != 0) + if((n = tdefl_flush_block(d, 0)) != 0) return (n < 0) ? MZ_FALSE : MZ_TRUE; total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; @@ -1559,14 +1559,14 @@ static mz_bool tdefl_compress_fast(tdefl_compressor *d) } } - while (lookahead_size) + while(lookahead_size) { mz_uint8 lit = d->m_dict[cur_pos]; total_lz_bytes++; *pLZ_code_buf++ = lit; *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); - if (--num_flags_left == 0) + if(--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; @@ -1579,7 +1579,7 @@ static mz_bool tdefl_compress_fast(tdefl_compressor *d) cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; lookahead_size--; - if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) + if(pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) { int n; d->m_lookahead_pos = lookahead_pos; @@ -1589,7 +1589,7 @@ static mz_bool tdefl_compress_fast(tdefl_compressor *d) d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; - if ((n = tdefl_flush_block(d, 0)) != 0) + if((n = tdefl_flush_block(d, 0)) != 0) return (n < 0) ? MZ_FALSE : MZ_TRUE; total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; @@ -1615,7 +1615,7 @@ static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 li d->m_total_lz_bytes++; *d->m_pLZ_code_buf++ = lit; *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); - if (--d->m_num_flags_left == 0) + if(--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; @@ -1639,7 +1639,7 @@ static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match d->m_pLZ_code_buf += 3; *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); - if (--d->m_num_flags_left == 0) + if(--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; @@ -1649,7 +1649,7 @@ static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127]; d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++; - if (match_len >= TDEFL_MIN_MATCH_LEN) + if(match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++; } @@ -1659,11 +1659,11 @@ static mz_bool tdefl_compress_normal(tdefl_compressor *d) size_t src_buf_left = d->m_src_buf_left; tdefl_flush flush = d->m_flush; - while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) + while((src_buf_left) || ((flush) && (d->m_lookahead_size))) { mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos; /* Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. */ - if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) + if((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) { mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2; mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]; @@ -1671,11 +1671,11 @@ static mz_bool tdefl_compress_normal(tdefl_compressor *d) const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process; src_buf_left -= num_bytes_to_process; d->m_lookahead_size += num_bytes_to_process; - while (pSrc != pSrc_end) + while(pSrc != pSrc_end) { mz_uint8 c = *pSrc++; d->m_dict[dst_pos] = c; - if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) + if(dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; @@ -1686,15 +1686,15 @@ static mz_bool tdefl_compress_normal(tdefl_compressor *d) } else { - while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) + while((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) { mz_uint8 c = *pSrc++; mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; src_buf_left--; d->m_dict[dst_pos] = c; - if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) + if(dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; - if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) + if((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) { mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2; mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); @@ -1704,7 +1704,7 @@ static mz_bool tdefl_compress_normal(tdefl_compressor *d) } } d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size); - if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) + if((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) break; /* Simple lazy/greedy parsing state machine. */ @@ -1712,19 +1712,19 @@ static mz_bool tdefl_compress_normal(tdefl_compressor *d) cur_match_dist = 0; cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; - if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) + if(d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) { - if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) + if((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) { mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK]; cur_match_len = 0; - while (cur_match_len < d->m_lookahead_size) + while(cur_match_len < d->m_lookahead_size) { - if (d->m_dict[cur_pos + cur_match_len] != c) + if(d->m_dict[cur_pos + cur_match_len] != c) break; cur_match_len++; } - if (cur_match_len < TDEFL_MIN_MATCH_LEN) + if(cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1; @@ -1734,16 +1734,16 @@ static mz_bool tdefl_compress_normal(tdefl_compressor *d) { tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len); } - if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) + if(((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) { cur_match_dist = cur_match_len = 0; } - if (d->m_saved_match_len) + if(d->m_saved_match_len) { - if (cur_match_len > d->m_saved_match_len) + if(cur_match_len > d->m_saved_match_len) { tdefl_record_literal(d, (mz_uint8)d->m_saved_lit); - if (cur_match_len >= 128) + if(cur_match_len >= 128) { tdefl_record_match(d, cur_match_len, cur_match_dist); d->m_saved_match_len = 0; @@ -1763,9 +1763,9 @@ static mz_bool tdefl_compress_normal(tdefl_compressor *d) d->m_saved_match_len = 0; } } - else if (!cur_match_dist) + else if(!cur_match_dist) tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]); - else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128)) + else if((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128)) { tdefl_record_match(d, cur_match_len, cur_match_dist); len_to_move = cur_match_len; @@ -1782,13 +1782,13 @@ static mz_bool tdefl_compress_normal(tdefl_compressor *d) d->m_lookahead_size -= len_to_move; d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, (mz_uint)TDEFL_LZ_DICT_SIZE); /* Check if it's time to flush the current LZ codes to the internal output buffer. */ - if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) || + if((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) || ((d->m_total_lz_bytes > 31 * 1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))) { int n; d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; - if ((n = tdefl_flush_block(d, 0)) != 0) + if((n = tdefl_flush_block(d, 0)) != 0) return (n < 0) ? MZ_FALSE : MZ_TRUE; } } @@ -1800,12 +1800,12 @@ static mz_bool tdefl_compress_normal(tdefl_compressor *d) static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) { - if (d->m_pIn_buf_size) + if(d->m_pIn_buf_size) { *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; } - if (d->m_pOut_buf_size) + if(d->m_pOut_buf_size) { size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining); memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n); @@ -1821,11 +1821,11 @@ static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush) { - if (!d) + if(!d) { - if (pIn_buf_size) + if(pIn_buf_size) *pIn_buf_size = 0; - if (pOut_buf_size) + if(pOut_buf_size) *pOut_buf_size = 0; return TDEFL_STATUS_BAD_PARAM; } @@ -1839,44 +1839,44 @@ tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pI d->m_out_buf_ofs = 0; d->m_flush = flush; - if (((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) || + if(((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) || (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf)) { - if (pIn_buf_size) + if(pIn_buf_size) *pIn_buf_size = 0; - if (pOut_buf_size) + if(pOut_buf_size) *pOut_buf_size = 0; return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM); } d->m_wants_to_finish |= (flush == TDEFL_FINISH); - if ((d->m_output_flush_remaining) || (d->m_finished)) + if((d->m_output_flush_remaining) || (d->m_finished)) return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES &&MINIZ_LITTLE_ENDIAN - if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) && + if(((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) && ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) && ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0)) { - if (!tdefl_compress_fast(d)) + if(!tdefl_compress_fast(d)) return d->m_prev_return_status; } else #endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */ { - if (!tdefl_compress_normal(d)) + if(!tdefl_compress_normal(d)) return d->m_prev_return_status; } - if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf)) + if((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf)) d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf); - if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining)) + if((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining)) { - if (tdefl_flush_block(d, flush) < 0) + if(tdefl_flush_block(d, flush) < 0) return d->m_prev_return_status; d->m_finished = (flush == TDEFL_FINISH); - if (flush == TDEFL_FULL_FLUSH) + if(flush == TDEFL_FULL_FLUSH) { MZ_CLEAR_OBJ(d->m_hash); MZ_CLEAR_OBJ(d->m_next); @@ -1901,7 +1901,7 @@ tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_fun d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0; d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3; - if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) + if(!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash); d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0; d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0; @@ -1940,10 +1940,10 @@ mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put { tdefl_compressor *pComp; mz_bool succeeded; - if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) + if(((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE; pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); - if (!pComp) + if(!pComp) return MZ_FALSE; succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY); succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE); @@ -1962,18 +1962,18 @@ static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser { tdefl_output_buffer *p = (tdefl_output_buffer *)pUser; size_t new_size = p->m_size + len; - if (new_size > p->m_capacity) + if(new_size > p->m_capacity) { size_t new_capacity = p->m_capacity; mz_uint8 *pNew_buf; - if (!p->m_expandable) + if(!p->m_expandable) return MZ_FALSE; do { new_capacity = MZ_MAX(128U, new_capacity << 1U); - } while (new_size > new_capacity); + } while(new_size > new_capacity); pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity); - if (!pNew_buf) + if(!pNew_buf) return MZ_FALSE; p->m_pBuf = pNew_buf; p->m_capacity = new_capacity; @@ -1987,12 +1987,12 @@ void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_ { tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); - if (!pOut_len) + if(!pOut_len) return nullptr; else *pOut_len = 0; out_buf.m_expandable = MZ_TRUE; - if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) + if(!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL; *pOut_len = out_buf.m_size; return out_buf.m_pBuf; @@ -2002,11 +2002,11 @@ size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void { tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); - if (!pOut_buf) + if(!pOut_buf) return 0; out_buf.m_pBuf = (mz_uint8 *)pOut_buf; out_buf.m_capacity = out_buf_len; - if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) + if(!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0; return out_buf.m_size; } @@ -2018,18 +2018,18 @@ static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 5 mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy) { mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); - if (window_bits > 0) + if(window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER; - if (!level) + if(!level) comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; - else if (strategy == MZ_FILTERED) + else if(strategy == MZ_FILTERED) comp_flags |= TDEFL_FILTER_MATCHES; - else if (strategy == MZ_HUFFMAN_ONLY) + else if(strategy == MZ_HUFFMAN_ONLY) comp_flags &= ~TDEFL_MAX_PROBES_MASK; - else if (strategy == MZ_FIXED) + else if(strategy == MZ_FIXED) comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS; - else if (strategy == MZ_RLE) + else if(strategy == MZ_RLE) comp_flags |= TDEFL_RLE_MATCHES; return comp_flags; @@ -2053,27 +2053,27 @@ void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int int i, bpl = w * num_chans, y, z; mz_uint32 c; *pLen_out = 0; - if (!pComp) + if(!pComp) return NULL; MZ_CLEAR_OBJ(out_buf); out_buf.m_expandable = MZ_TRUE; out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h); - if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity))) + if(NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity))) { MZ_FREE(pComp); return NULL; } /* write dummy header */ - for (z = 41; z; --z) + for(z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf); /* compress image data */ tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER); - for (y = 0; y < h; ++y) + for(y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); } - if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) + if(tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); @@ -2087,12 +2087,12 @@ void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int 0, 0, (mz_uint8)(w >> 8), (mz_uint8)w, 0, 0, (mz_uint8)(h >> 8), (mz_uint8)h, 8, chans[num_chans], 0, 0, 0, 0, 0, 0, 0, (mz_uint8)(*pLen_out >> 24), (mz_uint8)(*pLen_out >> 16), (mz_uint8)(*pLen_out >> 8), (mz_uint8) * pLen_out, 0x49, 0x44, 0x41, 0x54 }; c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17); - for (i = 0; i < 4; ++i, c <<= 8) + for(i = 0; i < 4; ++i, c <<= 8) ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24); memcpy(out_buf.m_pBuf, pnghdr, 41); } /* write footer (IDAT CRC-32, followed by IEND chunk) */ - if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) + if(!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); @@ -2100,7 +2100,7 @@ void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int return NULL; } c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, *pLen_out + 4); - for (i = 0; i < 4; ++i, c <<= 8) + for(i = 0; i < 4; ++i, c <<= 8) (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24); /* compute final size of file, grab compressed data buffer and return */ *pLen_out += 57; @@ -2171,7 +2171,7 @@ extern "C" { #define TINFL_MEMSET(p, c, l) memset(p, c, l) #define TINFL_CR_BEGIN \ - switch (r->m_state) \ + switch(r->m_state) \ { \ case 0: #define TINFL_CR_RETURN(state_index, result) \ @@ -2187,7 +2187,7 @@ extern "C" { #define TINFL_CR_RETURN_FOREVER(state_index, result) \ do \ { \ - for (;;) \ + for(;;) \ { \ TINFL_CR_RETURN(state_index, result); \ } \ @@ -2198,7 +2198,7 @@ extern "C" { #define TINFL_GET_BYTE(state_index, c) \ do \ { \ - while (pIn_buf_cur >= pIn_buf_end) \ + while(pIn_buf_cur >= pIn_buf_end) \ { \ TINFL_CR_RETURN(state_index, (decomp_flags &TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); \ } \ @@ -2213,11 +2213,11 @@ extern "C" { TINFL_GET_BYTE(state_index, c); \ bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \ num_bits += 8; \ - } while (num_bits < (mz_uint)(n)) + } while(num_bits < (mz_uint)(n)) #define TINFL_SKIP_BITS(state_index, n) \ do \ { \ - if (num_bits < (mz_uint)(n)) \ + if(num_bits < (mz_uint)(n)) \ { \ TINFL_NEED_BITS(state_index, n); \ } \ @@ -2228,7 +2228,7 @@ extern "C" { #define TINFL_GET_BITS(state_index, b, n) \ do \ { \ - if (num_bits < (mz_uint)(n)) \ + if(num_bits < (mz_uint)(n)) \ { \ TINFL_NEED_BITS(state_index, n); \ } \ @@ -2246,26 +2246,26 @@ extern "C" { do \ { \ temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \ - if (temp >= 0) \ + if(temp >= 0) \ { \ code_len = temp >> 9; \ - if ((code_len) && (num_bits >= code_len)) \ + if((code_len) && (num_bits >= code_len)) \ break; \ } \ - else if (num_bits > TINFL_FAST_LOOKUP_BITS) \ + else if(num_bits > TINFL_FAST_LOOKUP_BITS) \ { \ code_len = TINFL_FAST_LOOKUP_BITS; \ do \ { \ temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \ - } while ((temp < 0) && (num_bits >= (code_len + 1))); \ - if (temp >= 0) \ + } while((temp < 0) && (num_bits >= (code_len + 1))); \ + if(temp >= 0) \ break; \ } \ TINFL_GET_BYTE(state_index, c); \ bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \ num_bits += 8; \ - } while (num_bits < 15); + } while(num_bits < 15); /* TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read */ /* beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully */ @@ -2278,9 +2278,9 @@ extern "C" { { \ int temp; \ mz_uint code_len, c; \ - if (num_bits < 15) \ + if(num_bits < 15) \ { \ - if ((pIn_buf_end - pIn_buf_cur) < 2) \ + if((pIn_buf_end - pIn_buf_cur) < 2) \ { \ TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \ } \ @@ -2291,7 +2291,7 @@ extern "C" { num_bits += 16; \ } \ } \ - if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \ + if((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \ code_len = temp >> 9, temp &= 511; \ else \ { \ @@ -2299,7 +2299,7 @@ extern "C" { do \ { \ temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \ - } while (temp < 0); \ + } while(temp < 0); \ } \ sym = temp; \ bit_buf >>= code_len; \ @@ -2324,7 +2324,7 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t) - 1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start; /* Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). */ - if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) + if(((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; @@ -2340,14 +2340,14 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1; - if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) + if(decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) { TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1); counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8)); - if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) + if(!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4))))); - if (counter) + if(counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); } @@ -2357,38 +2357,38 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex { TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1; - if (r->m_type == 0) + if(r->m_type == 0) { TINFL_SKIP_BITS(5, num_bits & 7); - for (counter = 0; counter < 4; ++counter) + for(counter = 0; counter < 4; ++counter) { - if (num_bits) + if(num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); } - if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) + if((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); } - while ((counter) && (num_bits)) + while((counter) && (num_bits)) { TINFL_GET_BITS(51, dist, 8); - while (pOut_buf_cur >= pOut_buf_end) + while(pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); } *pOut_buf_cur++ = (mz_uint8)dist; counter--; } - while (counter) + while(counter) { size_t n; - while (pOut_buf_cur >= pOut_buf_end) + while(pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); } - while (pIn_buf_cur >= pIn_buf_end) + while(pIn_buf_cur >= pIn_buf_end) { TINFL_CR_RETURN(38, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); } @@ -2399,37 +2399,37 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex counter -= (mz_uint)n; } } - else if (r->m_type == 3) + else if(r->m_type == 3) { TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED); } else { - if (r->m_type == 1) + if(r->m_type == 1) { mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i; r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32); - for (i = 0; i <= 143; ++i) + for(i = 0; i <= 143; ++i) *p++ = 8; - for (; i <= 255; ++i) + for(; i <= 255; ++i) *p++ = 9; - for (; i <= 279; ++i) + for(; i <= 279; ++i) *p++ = 7; - for (; i <= 287; ++i) + for(; i <= 287; ++i) *p++ = 8; } else { - for (counter = 0; counter < 3; counter++) + for(counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; } MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); - for (counter = 0; counter < r->m_table_sizes[2]; counter++) + for(counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); @@ -2437,7 +2437,7 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex } r->m_table_sizes[2] = 19; } - for (; (int)r->m_type >= 0; r->m_type--) + for(; (int)r->m_type >= 0; r->m_type--) { int tree_next, tree_cur; tinfl_huff_table *pTable; @@ -2446,48 +2446,48 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree); - for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) + for(i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++; used_syms = 0, total = 0; next_code[0] = next_code[1] = 0; - for (i = 1; i <= 15; ++i) + for(i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); } - if ((65536 != total) && (used_syms > 1)) + if((65536 != total) && (used_syms > 1)) { TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED); } - for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index) + for(tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index) { mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; - if (!code_size) + if(!code_size) continue; cur_code = next_code[code_size]++; - for (l = code_size; l > 0; l--, cur_code >>= 1) + for(l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1); - if (code_size <= TINFL_FAST_LOOKUP_BITS) + if(code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); - while (rev_code < TINFL_FAST_LOOKUP_SIZE) + while(rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; } - if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) + if(0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1); - for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) + for(j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) { tree_cur -= ((rev_code >>= 1) & 1); - if (!pTable->m_tree[-tree_cur - 1]) + if(!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; @@ -2499,18 +2499,18 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index; } - if (r->m_type == 2) + if(r->m_type == 2) { - for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);) + for(counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);) { mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); - if (dist < 16) + if(dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; } - if ((dist == 16) && (!counter)) + if((dist == 16) && (!counter)) { TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED); } @@ -2520,7 +2520,7 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s; } - if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) + if((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) { TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED); } @@ -2528,17 +2528,17 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]); } } - for (;;) + for(;;) { mz_uint8 *pSrc; - for (;;) + for(;;) { - if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2)) + if(((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2)) { TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]); - if (counter >= 256) + if(counter >= 256) break; - while (pOut_buf_cur >= pOut_buf_end) + while(pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); } @@ -2549,21 +2549,21 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex int sym2; mz_uint code_len; #if TINFL_USE_64BIT_BITBUF - if (num_bits < 30) + if(num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; } #else - if (num_bits < 15) + if(num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } #endif - if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) + if((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) code_len = sym2 >> 9; else { @@ -2571,23 +2571,23 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; - } while (sym2 < 0); + } while(sym2 < 0); } counter = sym2; bit_buf >>= code_len; num_bits -= code_len; - if (counter & 256) + if(counter & 256) break; #if !TINFL_USE_64BIT_BITBUF - if (num_bits < 15) + if(num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } #endif - if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) + if((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) code_len = sym2 >> 9; else { @@ -2595,13 +2595,13 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; - } while (sym2 < 0); + } while(sym2 < 0); } bit_buf >>= code_len; num_bits -= code_len; pOut_buf_cur[0] = (mz_uint8)counter; - if (sym2 & 256) + if(sym2 & 256) { pOut_buf_cur++; counter = sym2; @@ -2611,12 +2611,12 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex pOut_buf_cur += 2; } } - if ((counter &= 511) == 256) + if((counter &= 511) == 256) break; num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257]; - if (num_extra) + if(num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); @@ -2626,7 +2626,7 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]); num_extra = s_dist_extra[dist]; dist = s_dist_base[dist]; - if (num_extra) + if(num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); @@ -2634,18 +2634,18 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex } dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start; - if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) + if((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) { TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED); } pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask); - if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) + if((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) { - while (counter--) + while(counter--) { - while (pOut_buf_cur >= pOut_buf_end) + while(pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); } @@ -2654,7 +2654,7 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex continue; } #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES - else if ((counter >= 9) && (counter <= dist)) + else if((counter >= 9) && (counter <= dist)) { const mz_uint8 *pSrc_end = pSrc + (counter & ~7); do @@ -2662,13 +2662,13 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0]; ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1]; pOut_buf_cur += 8; - } while ((pSrc += 8) < pSrc_end); - if ((counter &= 7) < 3) + } while((pSrc += 8) < pSrc_end); + if((counter &= 7) < 3) { - if (counter) + if(counter) { pOut_buf_cur[0] = pSrc[0]; - if (counter > 1) + if(counter > 1) pOut_buf_cur[1] = pSrc[1]; pOut_buf_cur += counter; } @@ -2683,22 +2683,22 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex pOut_buf_cur[2] = pSrc[2]; pOut_buf_cur += 3; pSrc += 3; - } while ((int)(counter -= 3) > 2); - if ((int)counter > 0) + } while((int)(counter -= 3) > 2); + if((int)counter > 0) { pOut_buf_cur[0] = pSrc[0]; - if ((int)counter > 1) + if((int)counter > 1) pOut_buf_cur[1] = pSrc[1]; pOut_buf_cur += counter; } } } - } while (!(r->m_final & 1)); + } while(!(r->m_final & 1)); /* Ensure byte alignment and put back any bytes from the bitbuf if we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */ /* I'm being super conservative here. A number of simplifications can be made to the byte alignment part, and the Adler32 check shouldn't ever need to worry about reading from the bitbuf now. */ TINFL_SKIP_BITS(32, num_bits & 7); - while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8)) + while((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8)) { --pIn_buf_cur; num_bits -= 8; @@ -2706,12 +2706,12 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex bit_buf &= (tinfl_bit_buf_t)((1ULL << num_bits) - 1ULL); MZ_ASSERT(!num_bits); /* if this assert fires then we've read beyond the end of non-deflate/zlib streams with following data (such as gzip streams). */ - if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) + if(decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) { - for (counter = 0; counter < 4; ++counter) + for(counter = 0; counter < 4; ++counter) { mz_uint s; - if (num_bits) + if(num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); @@ -2726,9 +2726,9 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex /* As long as we aren't telling the caller that we NEED more input to make forward progress: */ /* Put back any bytes from the bitbuf in case we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */ /* We need to be very careful here to NOT push back any bytes we definitely know we need to make forward progress, though, or we'll lock the caller up into an inf loop. */ - if ((status != TINFL_STATUS_NEEDS_MORE_INPUT) && (status != TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS)) + if((status != TINFL_STATUS_NEEDS_MORE_INPUT) && (status != TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS)) { - while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8)) + while((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8)) { --pIn_buf_cur; num_bits -= 8; @@ -2742,15 +2742,15 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex r->m_dist_from_out_buf_start = dist_from_out_buf_start; *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next; - if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0)) + if((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0)) { const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size; mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552; - while (buf_len) + while(buf_len) { - for (i = 0; i + 7 < block_len; i += 8, ptr += 8) + for(i = 0; i + 7 < block_len; i += 8, ptr += 8) { s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; @@ -2761,14 +2761,14 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; } - for (; i < block_len; ++i) + for(; i < block_len; ++i) s1 += *ptr++, s2 += s1; s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; } r->m_check_adler32 = (s2 << 16) + s1; - if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) + if((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH; } return status; @@ -2782,12 +2782,12 @@ void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, siz size_t src_buf_ofs = 0, out_buf_capacity = 0; *pOut_len = 0; tinfl_init(&decomp); - for (;;) + for(;;) { size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity; tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL, &dst_buf_size, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); - if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) + if((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) { MZ_FREE(pBuf); *pOut_len = 0; @@ -2795,13 +2795,13 @@ void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, siz } src_buf_ofs += src_buf_size; *pOut_len += dst_buf_size; - if (status == TINFL_STATUS_DONE) + if(status == TINFL_STATUS_DONE) break; new_out_buf_capacity = out_buf_capacity * 2; - if (new_out_buf_capacity < 128) + if(new_out_buf_capacity < 128) new_out_buf_capacity = 128; pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity); - if (!pNew_buf) + if(!pNew_buf) { MZ_FREE(pBuf); *pOut_len = 0; @@ -2828,18 +2828,18 @@ int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_decompressor decomp; mz_uint8 *pDict = (mz_uint8 *)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0; - if (!pDict) + if(!pDict) return TINFL_STATUS_FAILED; tinfl_init(&decomp); - for (;;) + for(;;) { size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs; tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size, (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); in_buf_ofs += in_buf_size; - if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user))) + if((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user))) break; - if (status != TINFL_STATUS_HAS_MORE_OUTPUT) + if(status != TINFL_STATUS_HAS_MORE_OUTPUT) { result = (status == TINFL_STATUS_DONE); break; @@ -2854,7 +2854,7 @@ int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_decompressor *tinfl_decompressor_alloc() { tinfl_decompressor *pDecomp = (tinfl_decompressor *)MZ_MALLOC(sizeof(tinfl_decompressor)); - if (pDecomp) + if(pDecomp) tinfl_init(pDecomp); return pDecomp; } @@ -2916,7 +2916,7 @@ static FILE *mz_fopen(const char *pFilename, const char *pMode) static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) { FILE *pFile = NULL; - if (freopen_s(&pFile, pPath, pMode, pStream)) + if(freopen_s(&pFile, pPath, pMode, pStream)) return NULL; return pFile; } @@ -3167,15 +3167,15 @@ static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array * void *pNew_p; size_t new_capacity = min_new_capacity; MZ_ASSERT(pArray->m_element_size); - if (pArray->m_capacity >= min_new_capacity) + if(pArray->m_capacity >= min_new_capacity) return MZ_TRUE; - if (growing) + if(growing) { new_capacity = MZ_MAX(1, pArray->m_capacity); - while (new_capacity < min_new_capacity) + while(new_capacity < min_new_capacity) new_capacity *= 2; } - if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) + if(NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) return MZ_FALSE; pArray->m_p = pNew_p; pArray->m_capacity = new_capacity; @@ -3184,9 +3184,9 @@ static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array * static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing) { - if (new_capacity > pArray->m_capacity) + if(new_capacity > pArray->m_capacity) { - if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) + if(!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) return MZ_FALSE; } return MZ_TRUE; @@ -3194,9 +3194,9 @@ static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_ static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing) { - if (new_size > pArray->m_capacity) + if(new_size > pArray->m_capacity) { - if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) + if(!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) return MZ_FALSE; } pArray->m_size = new_size; @@ -3211,7 +3211,7 @@ static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_ static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n) { size_t orig_size = pArray->m_size; - if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) + if(!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) return MZ_FALSE; memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size); return MZ_TRUE; @@ -3238,7 +3238,7 @@ static void mz_zip_time_t_to_dos_time(MZ_TIME_T time, mz_uint16 *pDOS_time, mz_u struct tm tm_struct; struct tm *tm = &tm_struct; errno_t err = localtime_s(tm, &time); - if (err) + if(err) { *pDOS_date = 0; *pDOS_time = 0; @@ -3258,7 +3258,7 @@ static mz_bool mz_zip_get_file_modified_time(const char *pFilename, MZ_TIME_T *p struct MZ_FILE_STAT_STRUCT file_stat; /* On Linux with x86 glibc, this call will fail on large files (I think >= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. */ - if (MZ_FILE_STAT(pFilename, &file_stat) != 0) + if(MZ_FILE_STAT(pFilename, &file_stat) != 0) return MZ_FALSE; *pTime = file_stat.st_mtime; @@ -3281,7 +3281,7 @@ static mz_bool mz_zip_set_file_times(const char *pFilename, MZ_TIME_T access_tim static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, mz_zip_error err_num) { - if (pZip) + if(pZip) pZip->m_last_error = err_num; return MZ_FALSE; } @@ -3289,14 +3289,14 @@ static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, mz_zip_erro static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint flags) { (void)flags; - if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) + if((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - if (!pZip->m_pAlloc) + if(!pZip->m_pAlloc) pZip->m_pAlloc = miniz_def_alloc_func; - if (!pZip->m_pFree) + if(!pZip->m_pFree) pZip->m_pFree = miniz_def_free_func; - if (!pZip->m_pRealloc) + if(!pZip->m_pRealloc) pZip->m_pRealloc = miniz_def_realloc_func; pZip->m_archive_size = 0; @@ -3304,7 +3304,7 @@ static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint flags) pZip->m_total_files = 0; pZip->m_last_error = MZ_ZIP_NO_ERROR; - if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) + if(NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); @@ -3329,9 +3329,9 @@ static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pC pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pE = pL + MZ_MIN(l_len, r_len); - while (pL < pE) + while(pL < pE) { - if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) + if((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) break; pL++; pR++; @@ -3358,41 +3358,41 @@ static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *p mz_uint32 start, end; const mz_uint32 size = pZip->m_total_files; - if (size <= 1U) + if(size <= 1U) return; pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); start = (size - 2U) >> 1U; - for (;;) + for(;;) { mz_uint64 child, root = start; - for (;;) + for(;;) { - if ((child = (root << 1U) + 1U) >= size) + if((child = (root << 1U) + 1U) >= size) break; child += (((child + 1U) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U]))); - if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) + if(!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) break; MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child; } - if (!start) + if(!start) break; start--; } end = size - 1; - while (end > 0) + while(end > 0) { mz_uint64 child, root = 0; MZ_SWAP_UINT32(pIndices[end], pIndices[0]); - for (;;) + for(;;) { - if ((child = (root << 1U) + 1U) >= end) + if((child = (root << 1U) + 1U) >= end) break; child += (((child + 1U) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U])); - if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) + if(!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) break; MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child; @@ -3408,36 +3408,36 @@ static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip, mz_uint32 r mz_uint8 *pBuf = (mz_uint8 *)buf_u32; /* Basic sanity checks - reject files which are too small */ - if (pZip->m_archive_size < record_size) + if(pZip->m_archive_size < record_size) return MZ_FALSE; /* Find the record by scanning the file from the end towards the beginning. */ cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0); - for (;;) + for(;;) { int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n) + if(pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n) return MZ_FALSE; - for (i = n - 4; i >= 0; --i) + for(i = n - 4; i >= 0; --i) { mz_uint s = MZ_READ_LE32(pBuf + i); - if (s == record_sig) + if(s == record_sig) { - if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size) + if((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size) break; } } - if (i >= 0) + if(i >= 0) { cur_file_ofs += i; break; } /* Give up if we've searched the entire file, or we've gone back "too far" (~64kb) */ - if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (MZ_UINT16_MAX + record_size))) + if((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (MZ_UINT16_MAX + record_size))) return MZ_FALSE; cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0); @@ -3466,32 +3466,32 @@ static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flag mz_uint64 zip64_end_of_central_dir_ofs = 0; /* Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. */ - if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + if(pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); - if (!mz_zip_reader_locate_header_sig(pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs)) + if(!mz_zip_reader_locate_header_sig(pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs)) return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR); /* Read and verify the end of central directory record. */ - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + if(pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) + if(MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); - if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) + if(cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) { - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE, pZip64_locator, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) + if(pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE, pZip64_locator, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) { - if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG) + if(MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG) { zip64_end_of_central_dir_ofs = MZ_READ_LE64(pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS); - if (zip64_end_of_central_dir_ofs > (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) + if(zip64_end_of_central_dir_ofs > (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); - if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs, pZip64_end_of_central_dir, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) + if(pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs, pZip64_end_of_central_dir, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) { - if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG) + if(MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG) { pZip->m_pState->m_zip64 = MZ_TRUE; } @@ -3507,7 +3507,7 @@ static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flag cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS); cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); - if (pZip->m_pState->m_zip64) + if(pZip->m_pState->m_zip64) { mz_uint32 zip64_total_num_of_disks = MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS); mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS); @@ -3515,25 +3515,25 @@ static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flag mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS); mz_uint64 zip64_size_of_central_directory = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS); - if (zip64_size_of_end_of_central_dir_record < (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12)) + if(zip64_size_of_end_of_central_dir_record < (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - if (zip64_total_num_of_disks != 1U) + if(zip64_total_num_of_disks != 1U) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); /* Check for miniz's practical limits */ - if (zip64_cdir_total_entries > MZ_UINT32_MAX) + if(zip64_cdir_total_entries > MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries; - if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX) + if(zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); cdir_entries_on_this_disk = (mz_uint32)zip64_cdir_total_entries_on_this_disk; /* Check for miniz's current practical limits (sorry, this should be enough for millions of files) */ - if (zip64_size_of_central_directory > MZ_UINT32_MAX) + if(zip64_size_of_central_directory > MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); cdir_size = (mz_uint32)zip64_size_of_central_directory; @@ -3545,50 +3545,50 @@ static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flag cdir_ofs = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS); } - if (pZip->m_total_files != cdir_entries_on_this_disk) + if(pZip->m_total_files != cdir_entries_on_this_disk) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); - if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1))) + if(((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1))) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); - if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) + if(cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) + if((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); pZip->m_central_directory_file_ofs = cdir_ofs; - if (pZip->m_total_files) + if(pZip->m_total_files) { mz_uint i, n; /* Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and possibly another to hold the sorted indices. */ - if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) || + if((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) || (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE))) return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - if (sort_central_dir) + if(sort_central_dir) { - if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE)) + if(!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE)) return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); } - if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size) + if(pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size) return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); /* Now create an index into the central directory file records, do some basic sanity checking on each record */ p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p; - for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) + for(n = cdir_size, i = 0; i < pZip->m_total_files; ++i) { mz_uint total_header_size, disk_index, bit_flags, filename_size, ext_data_size; mz_uint64 comp_size, decomp_size, local_header_ofs; - if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)) + if((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p); - if (sort_central_dir) + if(sort_central_dir) MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i; comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); @@ -3597,29 +3597,29 @@ static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flag filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS); - if ((!pZip->m_pState->m_zip64_has_extended_info_fields) && + if((!pZip->m_pState->m_zip64_has_extended_info_fields) && (ext_data_size) && (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == MZ_UINT32_MAX)) { /* Attempt to find zip64 extended information field in the entry's extra data */ mz_uint32 extra_size_remaining = ext_data_size; - if (extra_size_remaining) + if(extra_size_remaining) { const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size; do { - if (extra_size_remaining < (sizeof(mz_uint16) * 2)) + if(extra_size_remaining < (sizeof(mz_uint16) * 2)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); mz_uint32 field_id = MZ_READ_LE16(pExtra_data); mz_uint32 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); - if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining) + if((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) + if(field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) { /* Ok, the archive didn't have any zip64 headers but it uses a zip64 extended information field so mark it as zip64 anyway (this can occur with infozip's zip util when it reads compresses files from stdin). */ pZip->m_pState->m_zip64 = MZ_TRUE; @@ -3629,32 +3629,32 @@ static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flag pExtra_data += sizeof(mz_uint16) * 2 + field_data_size; extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size; - } while (extra_size_remaining); + } while(extra_size_remaining); } } /* I've seen archives that aren't marked as zip64 that uses zip64 ext data, argh */ - if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX)) + if((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX)) { - if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size)) + if(((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); } disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS); - if ((disk_index == MZ_UINT16_MAX) || ((disk_index != num_this_disk) && (disk_index != 1))) + if((disk_index == MZ_UINT16_MAX) || ((disk_index != num_this_disk) && (disk_index != 1))) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); - if (comp_size != MZ_UINT32_MAX) + if(comp_size != MZ_UINT32_MAX) { - if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size) + if(((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); } bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); - if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED) + if(bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); - if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n) + if((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); n -= total_header_size; @@ -3662,7 +3662,7 @@ static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flag } } - if (sort_central_dir) + if(sort_central_dir) mz_zip_reader_sort_central_dir_offsets_by_filename(pZip); return MZ_TRUE; @@ -3670,7 +3670,7 @@ static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flag void mz_zip_zero_struct(mz_zip_archive *pZip) { - if (pZip) + if(pZip) MZ_CLEAR_OBJ(*pZip); } @@ -3678,18 +3678,18 @@ static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, mz_bool set_last { mz_bool status = MZ_TRUE; - if (!pZip) + if(!pZip) return MZ_FALSE; - if ((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) + if((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) { - if (set_last_error) + if(set_last_error) pZip->m_last_error = MZ_ZIP_INVALID_PARAMETER; return MZ_FALSE; } - if (pZip->m_pState) + if(pZip->m_pState) { mz_zip_internal_state *pState = pZip->m_pState; pZip->m_pState = NULL; @@ -3699,13 +3699,13 @@ static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, mz_bool set_last mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); #ifndef MINIZ_NO_STDIO - if (pState->m_pFile) + if(pState->m_pFile) { - if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE) + if(pZip->m_zip_type == MZ_ZIP_TYPE_FILE) { - if (MZ_FCLOSE(pState->m_pFile) == EOF) + if(MZ_FCLOSE(pState->m_pFile) == EOF) { - if (set_last_error) + if(set_last_error) pZip->m_last_error = MZ_ZIP_FILE_CLOSE_FAILED; status = MZ_FALSE; } @@ -3727,16 +3727,16 @@ mz_bool mz_zip_reader_end(mz_zip_archive *pZip) } mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags) { - if ((!pZip) || (!pZip->m_pRead)) + if((!pZip) || (!pZip->m_pRead)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - if (!mz_zip_reader_init_internal(pZip, flags)) + if(!mz_zip_reader_init_internal(pZip, flags)) return MZ_FALSE; pZip->m_zip_type = MZ_ZIP_TYPE_USER; pZip->m_archive_size = size; - if (!mz_zip_reader_read_central_dir(pZip, flags)) + if(!mz_zip_reader_read_central_dir(pZip, flags)) { mz_zip_reader_end_internal(pZip, MZ_FALSE); return MZ_FALSE; @@ -3755,13 +3755,13 @@ static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags) { - if (!pMem) + if(!pMem) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - if (size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + if(size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); - if (!mz_zip_reader_init_internal(pZip, flags)) + if(!mz_zip_reader_init_internal(pZip, flags)) return MZ_FALSE; pZip->m_zip_type = MZ_ZIP_TYPE_MEMORY; @@ -3777,7 +3777,7 @@ mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t si pZip->m_pState->m_mem_size = size; - if (!mz_zip_reader_read_central_dir(pZip, flags)) + if(!mz_zip_reader_read_central_dir(pZip, flags)) { mz_zip_reader_end_internal(pZip, MZ_FALSE); return MZ_FALSE; @@ -3794,7 +3794,7 @@ static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBu file_ofs += pZip->m_pState->m_file_archive_start_ofs; - if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) + if(((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) return 0; return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile); @@ -3807,18 +3807,18 @@ mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_ mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags, mz_uint64 file_start_ofs, mz_uint64 archive_size) { - if ((!pZip) || (!pFilename) || ((archive_size) && (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE))) + if((!pZip) || (!pFilename) || ((archive_size) && (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE))) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); mz_uint64 file_size; MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb"); - if (!pFile) + if(!pFile) return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); file_size = archive_size; - if (!file_size) + if(!file_size) { - if (MZ_FSEEK64(pFile, 0, SEEK_END)) + if(MZ_FSEEK64(pFile, 0, SEEK_END)) { MZ_FCLOSE(pFile); return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED); @@ -3829,10 +3829,10 @@ mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, /* TODO: Better sanity check archive_size and the # of actual remaining bytes */ - if (file_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + if(file_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); - if (!mz_zip_reader_init_internal(pZip, flags)) + if(!mz_zip_reader_init_internal(pZip, flags)) { MZ_FCLOSE(pFile); return MZ_FALSE; @@ -3845,7 +3845,7 @@ mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, pZip->m_archive_size = file_size; pZip->m_pState->m_file_archive_start_ofs = file_start_ofs; - if (!mz_zip_reader_read_central_dir(pZip, flags)) + if(!mz_zip_reader_read_central_dir(pZip, flags)) { mz_zip_reader_end_internal(pZip, MZ_FALSE); return MZ_FALSE; @@ -3858,23 +3858,23 @@ mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 { mz_uint64 cur_file_ofs; - if ((!pZip) || (!pFile)) + if((!pZip) || (!pFile)) return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); cur_file_ofs = MZ_FTELL64(pFile); - if (!archive_size) + if(!archive_size) { - if (MZ_FSEEK64(pFile, 0, SEEK_END)) + if(MZ_FSEEK64(pFile, 0, SEEK_END)) return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED); archive_size = MZ_FTELL64(pFile) - cur_file_ofs; - if (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + if(archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); } - if (!mz_zip_reader_init_internal(pZip, flags)) + if(!mz_zip_reader_init_internal(pZip, flags)) return MZ_FALSE; pZip->m_zip_type = MZ_ZIP_TYPE_CFILE; @@ -3885,7 +3885,7 @@ mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 pZip->m_archive_size = archive_size; pZip->m_pState->m_file_archive_start_ofs = cur_file_ofs; - if (!mz_zip_reader_read_central_dir(pZip, flags)) + if(!mz_zip_reader_read_central_dir(pZip, flags)) { mz_zip_reader_end_internal(pZip, MZ_FALSE); return MZ_FALSE; @@ -3898,7 +3898,7 @@ mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 static MZ_FORCEINLINE const mz_uint8 *mz_zip_get_cdh(mz_zip_archive *pZip, mz_uint file_index) { - if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files)) + if((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files)) return NULL; return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); } @@ -3907,7 +3907,7 @@ mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index { mz_uint m_bit_flag; const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index); - if (!p) + if(!p) { mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); return MZ_FALSE; @@ -3923,7 +3923,7 @@ mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index mz_uint method; const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index); - if (!p) + if(!p) { mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); return MZ_FALSE; @@ -3932,19 +3932,19 @@ mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS); bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); - if ((method != 0) && (method != MZ_DEFLATED)) + if((method != 0) && (method != MZ_DEFLATED)) { mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD); return MZ_FALSE; } - if (bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) + if(bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) { mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); return MZ_FALSE; } - if (bit_flag & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG) + if(bit_flag & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG) { mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE); return MZ_FALSE; @@ -3957,16 +3957,16 @@ mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_ind { mz_uint filename_len, attribute_mapping_id, external_attr; const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index); - if (!p) + if(!p) { mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); return MZ_FALSE; } filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); - if (filename_len) + if(filename_len) { - if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/') + if(*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/') return MZ_TRUE; } @@ -3977,7 +3977,7 @@ mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_ind (void)attribute_mapping_id; external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); - if ((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0) + if((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0) { return MZ_TRUE; } @@ -3990,10 +3990,10 @@ static mz_bool mz_zip_file_stat_internal(mz_zip_archive *pZip, mz_uint file_inde mz_uint n; const mz_uint8 *p = pCentral_dir_header; - if (pFound_zip64_extra_data) + if(pFound_zip64_extra_data) *pFound_zip64_extra_data = MZ_FALSE; - if ((!p) || (!pStat)) + if((!p) || (!pStat)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); /* Extract fields from the central directory record. */ @@ -4032,37 +4032,37 @@ static mz_bool mz_zip_file_stat_internal(mz_zip_archive *pZip, mz_uint file_inde /* See if we need to read any zip64 extended information fields. */ /* Confusingly, these zip64 fields can be present even on non-zip64 archives (Debian zip on a huge files from stdin piped to stdout creates them). */ - if (MZ_MAX(MZ_MAX(pStat->m_comp_size, pStat->m_uncomp_size), pStat->m_local_header_ofs) == MZ_UINT32_MAX) + if(MZ_MAX(MZ_MAX(pStat->m_comp_size, pStat->m_uncomp_size), pStat->m_local_header_ofs) == MZ_UINT32_MAX) { /* Attempt to find zip64 extended information field in the entry's extra data */ mz_uint32 extra_size_remaining = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS); - if (extra_size_remaining) + if(extra_size_remaining) { const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); do { - if (extra_size_remaining < (sizeof(mz_uint16) * 2)) + if(extra_size_remaining < (sizeof(mz_uint16) * 2)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); mz_uint32 field_id = MZ_READ_LE16(pExtra_data); mz_uint32 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); - if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining) + if((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) + if(field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) { const mz_uint8 *pField_data = pExtra_data + sizeof(mz_uint16) * 2; mz_uint32 field_data_remaining = field_data_size; - if (pFound_zip64_extra_data) + if(pFound_zip64_extra_data) *pFound_zip64_extra_data = MZ_TRUE; - if (pStat->m_uncomp_size == MZ_UINT32_MAX) + if(pStat->m_uncomp_size == MZ_UINT32_MAX) { - if (field_data_remaining < sizeof(mz_uint64)) + if(field_data_remaining < sizeof(mz_uint64)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); pStat->m_uncomp_size = MZ_READ_LE64(pField_data); @@ -4070,9 +4070,9 @@ static mz_bool mz_zip_file_stat_internal(mz_zip_archive *pZip, mz_uint file_inde field_data_remaining -= sizeof(mz_uint64); } - if (pStat->m_comp_size == MZ_UINT32_MAX) + if(pStat->m_comp_size == MZ_UINT32_MAX) { - if (field_data_remaining < sizeof(mz_uint64)) + if(field_data_remaining < sizeof(mz_uint64)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); pStat->m_comp_size = MZ_READ_LE64(pField_data); @@ -4080,9 +4080,9 @@ static mz_bool mz_zip_file_stat_internal(mz_zip_archive *pZip, mz_uint file_inde field_data_remaining -= sizeof(mz_uint64); } - if (pStat->m_local_header_ofs == MZ_UINT32_MAX) + if(pStat->m_local_header_ofs == MZ_UINT32_MAX) { - if (field_data_remaining < sizeof(mz_uint64)) + if(field_data_remaining < sizeof(mz_uint64)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); pStat->m_local_header_ofs = MZ_READ_LE64(pField_data); @@ -4095,7 +4095,7 @@ static mz_bool mz_zip_file_stat_internal(mz_zip_archive *pZip, mz_uint file_inde pExtra_data += sizeof(mz_uint16) * 2 + field_data_size; extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size; - } while (extra_size_remaining); + } while(extra_size_remaining); } } @@ -4105,10 +4105,10 @@ static mz_bool mz_zip_file_stat_internal(mz_zip_archive *pZip, mz_uint file_inde static MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags) { mz_uint i; - if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE) + if(flags & MZ_ZIP_FLAG_CASE_SENSITIVE) return 0 == memcmp(pA, pB, len); - for (i = 0; i < len; ++i) - if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i])) + for(i = 0; i < len; ++i) + if(MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i])) return MZ_FALSE; return MZ_TRUE; } @@ -4120,9 +4120,9 @@ static MZ_FORCEINLINE int mz_zip_filename_compare(const mz_zip_array *pCentral_d mz_uint8 l = 0, r = 0; pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pE = pL + MZ_MIN(l_len, r_len); - while (pL < pE) + while(pL < pE) { - if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) + if((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) break; pL++; pR++; @@ -4139,28 +4139,28 @@ static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, const char const uint32_t size = pZip->m_total_files; const mz_uint filename_len = (mz_uint)strlen(pFilename); - if (pIndex) + if(pIndex) *pIndex = 0; - if (size) + if(size) { /* yes I could use uint32_t's, but then we would have to add some special case checks in the loop, argh, and */ /* honestly the major expense here on 32-bit CPU's will still be the filename compare */ mz_int64 l = 0, h = (mz_int64)size - 1; - while (l <= h) + while(l <= h) { mz_int64 m = l + ((h - l) >> 1); uint32_t file_index = pIndices[(uint32_t)m]; int comp = mz_zip_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len); - if (!comp) + if(!comp) { - if (pIndex) + if(pIndex) *pIndex = file_index; return MZ_TRUE; } - else if (comp < 0) + else if(comp < 0) l = m + 1; else h = m - 1; @@ -4173,7 +4173,7 @@ static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, const char int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags) { mz_uint32 index; - if (!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, &index)) + if(!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, &index)) return -1; else return (int)index; @@ -4184,14 +4184,14 @@ mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, co mz_uint file_index; size_t name_len, comment_len; - if (pIndex) + if(pIndex) *pIndex = 0; - if ((!pZip) || (!pZip->m_pState) || (!pName)) + if((!pZip) || (!pZip->m_pState) || (!pName)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); /* See if we can use a binary search */ - if (((pZip->m_pState->m_init_flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) && + if(((pZip->m_pState->m_init_flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) && (pZip->m_zip_mode == MZ_ZIP_MODE_READING) && ((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size)) { @@ -4200,42 +4200,42 @@ mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, co /* Locate the entry by scanning the entire central directory */ name_len = strlen(pName); - if (name_len > MZ_UINT16_MAX) + if(name_len > MZ_UINT16_MAX) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); comment_len = pComment ? strlen(pComment) : 0; - if (comment_len > MZ_UINT16_MAX) + if(comment_len > MZ_UINT16_MAX) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - for (file_index = 0; file_index < pZip->m_total_files; file_index++) + for(file_index = 0; file_index < pZip->m_total_files; file_index++) { const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS); const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; - if (filename_len < name_len) + if(filename_len < name_len) continue; - if (comment_len) + if(comment_len) { mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS); const char *pFile_comment = pFilename + filename_len + file_extra_len; - if ((file_comment_len != comment_len) || (!mz_zip_string_equal(pComment, pFile_comment, file_comment_len, flags))) + if((file_comment_len != comment_len) || (!mz_zip_string_equal(pComment, pFile_comment, file_comment_len, flags))) continue; } - if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) + if((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) { int ofs = filename_len - 1; do { - if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':')) + if((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':')) break; - } while (--ofs >= 0); + } while(--ofs >= 0); ofs++; pFilename += ofs; filename_len -= ofs; } - if ((filename_len == name_len) && (mz_zip_string_equal(pName, pFilename, filename_len, flags))) + if((filename_len == name_len) && (mz_zip_string_equal(pName, pFilename, filename_len, flags))) { - if (pIndex) + if(pIndex) *pIndex = file_index; return MZ_TRUE; } @@ -4254,51 +4254,51 @@ mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; tinfl_decompressor inflator; - if ((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) || ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead)) + if((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) || ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + if(!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) return MZ_FALSE; /* A directory or zero length file */ - if ((file_stat.m_is_directory) || (!file_stat.m_comp_size)) + if((file_stat.m_is_directory) || (!file_stat.m_comp_size)) return MZ_TRUE; /* Encryption and patch files are not supported. */ - if (file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)) + if(file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); /* This function only supports decompressing stored and deflate. */ - if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) + if((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD); /* Ensure supplied output buffer is large enough. */ needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size; - if (buf_size < needed_size) + if(buf_size < needed_size) return mz_zip_set_error(pZip, MZ_ZIP_BUF_TOO_SMALL); /* Read and parse the local directory entry. */ cur_file_ofs = file_stat.m_local_header_ofs; - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + if(pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + if(MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); - if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) + if((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) + if((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) { /* The file is stored or the caller has requested the compressed data. */ - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size) + if(pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size) return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS - if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0) + if((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0) { - if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32) + if(mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32) return mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED); } #endif @@ -4309,17 +4309,17 @@ mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file /* Decompress the file either directly from memory or from a file input buffer. */ tinfl_init(&inflator); - if (pZip->m_pState->m_pMem) + if(pZip->m_pState->m_pMem) { /* Read directly from the archive in memory. */ pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; read_buf_size = read_buf_avail = file_stat.m_comp_size; comp_remaining = 0; } - else if (pUser_read_buf) + else if(pUser_read_buf) { /* Use a user provided read buffer. */ - if (!user_read_buf_size) + if(!user_read_buf_size) return MZ_FALSE; pRead_buf = (mz_uint8 *)pUser_read_buf; read_buf_size = user_read_buf_size; @@ -4330,10 +4330,10 @@ mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file { /* Temporarily allocate a read buffer. */ read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE); - if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) + if(((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) + if(NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); read_buf_avail = 0; @@ -4344,10 +4344,10 @@ mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file { /* The size_t cast here should be OK because we've verified that the output buffer is >= file_stat.m_uncomp_size above */ size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs); - if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) + if((!read_buf_avail) && (!pZip->m_pState->m_pMem)) { read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + if(pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) { status = TINFL_STATUS_FAILED; mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED); @@ -4362,18 +4362,18 @@ mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file read_buf_avail -= in_buf_size; read_buf_ofs += in_buf_size; out_buf_ofs += out_buf_size; - } while (status == TINFL_STATUS_NEEDS_MORE_INPUT); + } while(status == TINFL_STATUS_NEEDS_MORE_INPUT); - if (status == TINFL_STATUS_DONE) + if(status == TINFL_STATUS_DONE) { /* Make sure the entire file was decompressed, and check its CRC. */ - if (out_buf_ofs != file_stat.m_uncomp_size) + if(out_buf_ofs != file_stat.m_uncomp_size) { mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE); status = TINFL_STATUS_FAILED; } #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS - else if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32) + else if(mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32) { mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED); status = TINFL_STATUS_FAILED; @@ -4381,7 +4381,7 @@ mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file #endif } - if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf)) + if((!pZip->m_pState->m_pMem) && (!pUser_read_buf)) pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); return status == TINFL_STATUS_DONE; @@ -4390,7 +4390,7 @@ mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) { mz_uint32 file_index; - if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index)) + if(!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index)) return MZ_FALSE; return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size); } @@ -4411,10 +4411,10 @@ void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, si const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index); void *pBuf; - if (pSize) + if(pSize) *pSize = 0; - if (!p) + if(!p) { mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); return NULL; @@ -4424,25 +4424,25 @@ void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, si uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size; - if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) + if(((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) { mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); return NULL; } - if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size))) + if(NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size))) { mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); return NULL; } - if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags)) + if(!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags)) { pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); return NULL; } - if (pSize) + if(pSize) *pSize = (size_t)alloc_size; return pBuf; } @@ -4450,9 +4450,9 @@ void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, si void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags) { mz_uint32 file_index; - if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index)) + if(!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index)) { - if (pSize) + if(pSize) *pSize = 0; return nullptr; } @@ -4470,38 +4470,38 @@ mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_ind mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; - if ((!pZip) || (!pZip->m_pState) || (!pCallback) || (!pZip->m_pRead)) + if((!pZip) || (!pZip->m_pState) || (!pCallback) || (!pZip->m_pRead)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + if(!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) return MZ_FALSE; /* A directory or zero length file */ - if ((file_stat.m_is_directory) || (!file_stat.m_comp_size)) + if((file_stat.m_is_directory) || (!file_stat.m_comp_size)) return MZ_TRUE; /* Encryption and patch files are not supported. */ - if (file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)) + if(file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); /* This function only supports decompressing stored and deflate. */ - if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) + if((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD); /* Read and do some minimal validation of the local directory entry (this doesn't crack the zip64 stuff, which we already have from the central dir) */ cur_file_ofs = file_stat.m_local_header_ofs; - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + if(pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + if(MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); - if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) + if((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); /* Decompress the file either directly from memory or from a file input buffer. */ - if (pZip->m_pState->m_pMem) + if(pZip->m_pState->m_pMem) { pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; read_buf_size = read_buf_avail = file_stat.m_comp_size; @@ -4510,27 +4510,27 @@ mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_ind else { read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE); - if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) + if(NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); read_buf_avail = 0; comp_remaining = file_stat.m_comp_size; } - if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) + if((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) { /* The file is stored or the caller has requested the compressed data. */ - if (pZip->m_pState->m_pMem) + if(pZip->m_pState->m_pMem) { - if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > MZ_UINT32_MAX)) + if(((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > MZ_UINT32_MAX)) return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size) + if(pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size) { mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED); status = TINFL_STATUS_FAILED; } - else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + else if(!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) { #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size); @@ -4543,10 +4543,10 @@ mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_ind } else { - while (comp_remaining) + while(comp_remaining) { read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + if(pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) { mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); status = TINFL_STATUS_FAILED; @@ -4554,13 +4554,13 @@ mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_ind } #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS - if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + if(!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) { file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail); } #endif - if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + if(pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) { mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED); status = TINFL_STATUS_FAILED; @@ -4578,7 +4578,7 @@ mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_ind tinfl_decompressor inflator; tinfl_init(&inflator); - if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE))) + if(NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE))) { mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); status = TINFL_STATUS_FAILED; @@ -4589,10 +4589,10 @@ mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_ind { mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); - if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) + if((!read_buf_avail) && (!pZip->m_pState->m_pMem)) { read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + if(pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) { mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); status = TINFL_STATUS_FAILED; @@ -4608,9 +4608,9 @@ mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_ind read_buf_avail -= in_buf_size; read_buf_ofs += in_buf_size; - if (out_buf_size) + if(out_buf_size) { - if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size) + if(pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size) { mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED); status = TINFL_STATUS_FAILED; @@ -4620,27 +4620,27 @@ mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_ind #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size); #endif - if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) + if((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) { mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED); status = TINFL_STATUS_FAILED; break; } } - } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT)); + } while((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT)); } } - if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) + if((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) { /* Make sure the entire file was decompressed, and check its CRC. */ - if (out_buf_ofs != file_stat.m_uncomp_size) + if(out_buf_ofs != file_stat.m_uncomp_size) { mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE); status = TINFL_STATUS_FAILED; } #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS - else if (file_crc32 != file_stat.m_crc32) + else if(file_crc32 != file_stat.m_crc32) { mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED); status = TINFL_STATUS_FAILED; @@ -4648,10 +4648,10 @@ mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_ind #endif } - if (!pZip->m_pState->m_pMem) + if(!pZip->m_pState->m_pMem) pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - if (pWrite_buf) + if(pWrite_buf) pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf); return status == TINFL_STATUS_DONE; @@ -4660,7 +4660,7 @@ mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_ind mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) { mz_uint32 file_index; - if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index)) + if(!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index)) return MZ_FALSE; return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags); @@ -4680,28 +4680,28 @@ mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat file_stat; MZ_FILE *pFile; - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + if(!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) return MZ_FALSE; - if ((file_stat.m_is_directory) || (!file_stat.m_is_supported)) + if((file_stat.m_is_directory) || (!file_stat.m_is_supported)) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE); pFile = MZ_FOPEN(pDst_filename, "wb"); - if (!pFile) + if(!pFile) return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags); - if (MZ_FCLOSE(pFile) == EOF) + if(MZ_FCLOSE(pFile) == EOF) { - if (status) + if(status) mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED); status = MZ_FALSE; } #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO) - if (status) + if(status) mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time); #endif @@ -4711,7 +4711,7 @@ mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags) { mz_uint32 file_index; - if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index)) + if(!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index)) return MZ_FALSE; return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags); @@ -4721,10 +4721,10 @@ mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index, { mz_zip_archive_file_stat file_stat; - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + if(!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) return MZ_FALSE; - if ((file_stat.m_is_directory) || (!file_stat.m_is_supported)) + if((file_stat.m_is_directory) || (!file_stat.m_is_supported)) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE); return mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags); @@ -4733,7 +4733,7 @@ mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index, mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags) { mz_uint32 file_index; - if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index)) + if(!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index)) return MZ_FALSE; return mz_zip_reader_extract_to_cfile(pZip, file_index, pFile, flags); @@ -4767,40 +4767,40 @@ mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint f mz_zip_array file_data_array; mz_zip_array_init(&file_data_array, 1); - if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead)) + if((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - if (file_index > pZip->m_total_files) + if(file_index > pZip->m_total_files) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); pState = pZip->m_pState; pCentral_dir_header = mz_zip_get_cdh(pZip, file_index); - if (!mz_zip_file_stat_internal(pZip, file_index, pCentral_dir_header, &file_stat, &found_zip64_ext_data_in_cdir)) + if(!mz_zip_file_stat_internal(pZip, file_index, pCentral_dir_header, &file_stat, &found_zip64_ext_data_in_cdir)) return MZ_FALSE; /* A directory or zero length file */ - if ((file_stat.m_is_directory) || (!file_stat.m_uncomp_size)) + if((file_stat.m_is_directory) || (!file_stat.m_uncomp_size)) return MZ_TRUE; /* Encryption and patch files are not supported. */ - if (file_stat.m_is_encrypted) + if(file_stat.m_is_encrypted) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); /* This function only supports stored and deflate. */ - if ((file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) + if((file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD); - if (!file_stat.m_is_supported) + if(!file_stat.m_is_supported) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE); /* Read and parse the local directory entry. */ local_header_ofs = file_stat.m_local_header_ofs; - if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + if(pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + if(MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); local_header_filename_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS); @@ -4811,34 +4811,34 @@ mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint f local_header_bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS); has_data_descriptor = (local_header_bit_flags & 8) != 0; - if (local_header_filename_len != strlen(file_stat.m_filename)) + if(local_header_filename_len != strlen(file_stat.m_filename)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - if ((local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size) > pZip->m_archive_size) + if((local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size) > pZip->m_archive_size) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - if (!mz_zip_array_resize(pZip, &file_data_array, MZ_MAX(local_header_filename_len, local_header_extra_len), MZ_FALSE)) + if(!mz_zip_array_resize(pZip, &file_data_array, MZ_MAX(local_header_filename_len, local_header_extra_len), MZ_FALSE)) return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - if (local_header_filename_len) + if(local_header_filename_len) { - if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE, file_data_array.m_p, local_header_filename_len) != local_header_filename_len) + if(pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE, file_data_array.m_p, local_header_filename_len) != local_header_filename_len) { mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); goto handle_failure; } /* I've seen 1 archive that had the same pathname, but used backslashes in the local dir and forward slashes in the central dir. Do we care about this? For now, this case will fail validation. */ - if (memcmp(file_stat.m_filename, file_data_array.m_p, local_header_filename_len) != 0) + if(memcmp(file_stat.m_filename, file_data_array.m_p, local_header_filename_len) != 0) { mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); goto handle_failure; } } - if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX))) + if((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX))) { - if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len, file_data_array.m_p, local_header_extra_len) != local_header_extra_len) + if(pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len, file_data_array.m_p, local_header_extra_len) != local_header_extra_len) { mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); goto handle_failure; @@ -4851,21 +4851,21 @@ mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint f { mz_uint32 field_id, field_data_size, field_total_size; - if (extra_size_remaining < (sizeof(mz_uint16) * 2)) + if(extra_size_remaining < (sizeof(mz_uint16) * 2)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); field_id = MZ_READ_LE16(pExtra_data); field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); field_total_size = field_data_size + sizeof(mz_uint16) * 2; - if (field_total_size > extra_size_remaining) + if(field_total_size > extra_size_remaining) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) + if(field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) { const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32); - if (field_data_size < sizeof(mz_uint64) * 2) + if(field_data_size < sizeof(mz_uint64) * 2) { mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); goto handle_failure; @@ -4880,18 +4880,18 @@ mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint f pExtra_data += field_total_size; extra_size_remaining -= field_total_size; - } while (extra_size_remaining); + } while(extra_size_remaining); } /* TODO: parse local header extra data when local_header_comp_size is 0xFFFFFFFF! (big_descriptor.zip) */ /* I've seen zips in the wild with the data descriptor bit set, but proper local header values and bogus data descriptors */ - if ((has_data_descriptor) && (!local_header_comp_size) && (!local_header_crc32)) + if((has_data_descriptor) && (!local_header_comp_size) && (!local_header_crc32)) { mz_uint8 descriptor_buf[32]; mz_uint32 num_descriptor_uint32s = ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) ? 6 : 4; - if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size, descriptor_buf, sizeof(mz_uint32) * num_descriptor_uint32s) != (sizeof(mz_uint32) * num_descriptor_uint32s)) + if(pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size, descriptor_buf, sizeof(mz_uint32) * num_descriptor_uint32s) != (sizeof(mz_uint32) * num_descriptor_uint32s)) { mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); goto handle_failure; @@ -4903,7 +4903,7 @@ mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint f mz_uint32 file_crc32 = MZ_READ_LE32(pSrc); mz_uint64 comp_size = 0, uncomp_size = 0; - if ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) + if((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) { comp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32)); uncomp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32) + sizeof(mz_uint64)); @@ -4914,7 +4914,7 @@ mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint f uncomp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32) + sizeof(mz_uint32)); } - if ((file_crc32 != file_stat.m_crc32) || (comp_size != file_stat.m_comp_size) || (uncomp_size != file_stat.m_uncomp_size)) + if((file_crc32 != file_stat.m_crc32) || (comp_size != file_stat.m_comp_size) || (uncomp_size != file_stat.m_uncomp_size)) { mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); goto handle_failure; @@ -4922,7 +4922,7 @@ mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint f } else { - if ((local_header_crc32 != file_stat.m_crc32) || (local_header_comp_size != file_stat.m_comp_size) || (local_header_uncomp_size != file_stat.m_uncomp_size)) + if((local_header_crc32 != file_stat.m_crc32) || (local_header_comp_size != file_stat.m_comp_size) || (local_header_uncomp_size != file_stat.m_uncomp_size)) { mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); goto handle_failure; @@ -4931,13 +4931,13 @@ mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint f mz_zip_array_clear(pZip, &file_data_array); - if ((flags & MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY) == 0) + if((flags & MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY) == 0) { - if (!mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_compute_crc32_callback, &uncomp_crc32, 0)) + if(!mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_compute_crc32_callback, &uncomp_crc32, 0)) return MZ_FALSE; /* 1 more check to be sure, although the extract checks too. */ - if (uncomp_crc32 != file_stat.m_crc32) + if(uncomp_crc32 != file_stat.m_crc32) { mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); return MZ_FALSE; @@ -4956,48 +4956,48 @@ mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags) mz_zip_internal_state *pState; uint32_t i; - if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead)) + if((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); pState = pZip->m_pState; /* Basic sanity checks */ - if (!pState->m_zip64) + if(!pState->m_zip64) { - if (pZip->m_total_files > MZ_UINT16_MAX) + if(pZip->m_total_files > MZ_UINT16_MAX) return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); - if (pZip->m_archive_size > MZ_UINT32_MAX) + if(pZip->m_archive_size > MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); } else { - if (pZip->m_total_files >= MZ_UINT32_MAX) + if(pZip->m_total_files >= MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); - if (pState->m_central_dir.m_size >= MZ_UINT32_MAX) + if(pState->m_central_dir.m_size >= MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); } - for (i = 0; i < pZip->m_total_files; i++) + for(i = 0; i < pZip->m_total_files; i++) { - if (MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG & flags) + if(MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG & flags) { mz_uint32 found_index; mz_zip_archive_file_stat stat; - if (!mz_zip_reader_file_stat(pZip, i, &stat)) + if(!mz_zip_reader_file_stat(pZip, i, &stat)) return MZ_FALSE; - if (!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, NULL, 0, &found_index)) + if(!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, NULL, 0, &found_index)) return MZ_FALSE; /* This check can fail if there are duplicate filenames in the archive (which we don't check for when writing - that's up to the user) */ - if (found_index != i) + if(found_index != i) return mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); } - if (!mz_zip_validate_file(pZip, i, flags)) + if(!mz_zip_validate_file(pZip, i, flags)) return MZ_FALSE; } @@ -5010,36 +5010,36 @@ mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags mz_zip_archive zip; mz_zip_error actual_err = MZ_ZIP_NO_ERROR; - if ((!pMem) || (!size)) + if((!pMem) || (!size)) { - if (pErr) + if(pErr) *pErr = MZ_ZIP_INVALID_PARAMETER; return MZ_FALSE; } mz_zip_zero_struct(&zip); - if (!mz_zip_reader_init_mem(&zip, pMem, size, flags)) + if(!mz_zip_reader_init_mem(&zip, pMem, size, flags)) { - if (pErr) + if(pErr) *pErr = zip.m_last_error; return MZ_FALSE; } - if (!mz_zip_validate_archive(&zip, flags)) + if(!mz_zip_validate_archive(&zip, flags)) { actual_err = zip.m_last_error; success = MZ_FALSE; } - if (!mz_zip_reader_end_internal(&zip, success)) + if(!mz_zip_reader_end_internal(&zip, success)) { - if (!actual_err) + if(!actual_err) actual_err = zip.m_last_error; success = MZ_FALSE; } - if (pErr) + if(pErr) *pErr = actual_err; return success; @@ -5052,36 +5052,36 @@ mz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zi mz_zip_archive zip; mz_zip_error actual_err = MZ_ZIP_NO_ERROR; - if (!pFilename) + if(!pFilename) { - if (pErr) + if(pErr) *pErr = MZ_ZIP_INVALID_PARAMETER; return MZ_FALSE; } mz_zip_zero_struct(&zip); - if (!mz_zip_reader_init_file_v2(&zip, pFilename, flags, 0, 0)) + if(!mz_zip_reader_init_file_v2(&zip, pFilename, flags, 0, 0)) { - if (pErr) + if(pErr) *pErr = zip.m_last_error; return MZ_FALSE; } - if (!mz_zip_validate_archive(&zip, flags)) + if(!mz_zip_validate_archive(&zip, flags)) { actual_err = zip.m_last_error; success = MZ_FALSE; } - if (!mz_zip_reader_end_internal(&zip, success)) + if(!mz_zip_reader_end_internal(&zip, success)) { - if (!actual_err) + if(!actual_err) actual_err = zip.m_last_error; success = MZ_FALSE; } - if (pErr) + if(pErr) *pErr = actual_err; return success; @@ -5120,25 +5120,25 @@ static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const vo mz_zip_internal_state *pState = pZip->m_pState; mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size); - if (!n) + if(!n) return 0; /* An allocation this big is likely to just fail on 32-bit systems, so don't even go there. */ - if ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)) + if((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)) { mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE); return 0; } - if (new_size > pState->m_mem_capacity) + if(new_size > pState->m_mem_capacity) { void *pNew_block; size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); - while (new_capacity < new_size) + while(new_capacity < new_size) new_capacity *= 2; - if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity))) + if(NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity))) { mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); return 0; @@ -5157,9 +5157,9 @@ static mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip, mz_bool set_last mz_zip_internal_state *pState; mz_bool status = MZ_TRUE; - if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))) + if((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))) { - if (set_last_error) + if(set_last_error) mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); return MZ_FALSE; } @@ -5171,13 +5171,13 @@ static mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip, mz_bool set_last mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); #ifndef MINIZ_NO_STDIO - if (pState->m_pFile) + if(pState->m_pFile) { - if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE) + if(pZip->m_zip_type == MZ_ZIP_TYPE_FILE) { - if (MZ_FCLOSE(pState->m_pFile) == EOF) + if(MZ_FCLOSE(pState->m_pFile) == EOF) { - if (set_last_error) + if(set_last_error) mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED); status = MZ_FALSE; } @@ -5187,7 +5187,7 @@ static mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip, mz_bool set_last } #endif /* #ifndef MINIZ_NO_STDIO */ - if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) + if((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) { pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem); pState->m_pMem = NULL; @@ -5202,34 +5202,34 @@ mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_ { mz_bool zip64 = (flags & MZ_ZIP_FLAG_WRITE_ZIP64) != 0; - if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) + if((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) + if(flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) { - if (!pZip->m_pRead) + if(!pZip->m_pRead) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); } - if (pZip->m_file_offset_alignment) + if(pZip->m_file_offset_alignment) { /* Ensure user specified file offset alignment is a power of 2. */ - if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1)) + if(pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); } - if (!pZip->m_pAlloc) + if(!pZip->m_pAlloc) pZip->m_pAlloc = miniz_def_alloc_func; - if (!pZip->m_pFree) + if(!pZip->m_pFree) pZip->m_pFree = miniz_def_free_func; - if (!pZip->m_pRealloc) + if(!pZip->m_pRealloc) pZip->m_pRealloc = miniz_def_realloc_func; pZip->m_archive_size = existing_size; pZip->m_central_directory_file_ofs = 0; pZip->m_total_files = 0; - if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) + if(NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); @@ -5256,19 +5256,19 @@ mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_ { pZip->m_pWrite = mz_zip_heap_write_func; - if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) + if(flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) pZip->m_pRead = mz_zip_mem_read_func; pZip->m_pIO_opaque = pZip; - if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags)) + if(!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags)) return MZ_FALSE; pZip->m_zip_type = MZ_ZIP_TYPE_HEAP; - if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning))) + if(0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning))) { - if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size))) + if(NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size))) { mz_zip_writer_end_internal(pZip, MZ_FALSE); return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); @@ -5292,7 +5292,7 @@ static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const vo file_ofs += pZip->m_pState->m_file_archive_start_ofs; - if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) + if(((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) { mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED); return 0; @@ -5312,15 +5312,15 @@ mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, pZip->m_pWrite = mz_zip_file_write_func; - if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) + if(flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) pZip->m_pRead = mz_zip_file_read_func; pZip->m_pIO_opaque = pZip; - if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags)) + if(!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags)) return MZ_FALSE; - if (NULL == (pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) ? "w+b" : "wb"))) + if(NULL == (pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) ? "w+b" : "wb"))) { mz_zip_writer_end(pZip); return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); @@ -5329,7 +5329,7 @@ mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, pZip->m_pState->m_pFile = pFile; pZip->m_zip_type = MZ_ZIP_TYPE_FILE; - if (size_to_reserve_at_beginning) + if(size_to_reserve_at_beginning) { mz_uint64 cur_ofs = 0; char buf[4096]; @@ -5339,14 +5339,14 @@ mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, do { size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) + if(pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) { mz_zip_writer_end(pZip); return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); } cur_ofs += n; size_to_reserve_at_beginning -= n; - } while (size_to_reserve_at_beginning); + } while(size_to_reserve_at_beginning); } return MZ_TRUE; @@ -5356,12 +5356,12 @@ mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint f { pZip->m_pWrite = mz_zip_file_write_func; - if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) + if(flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) pZip->m_pRead = mz_zip_file_read_func; pZip->m_pIO_opaque = pZip; - if (!mz_zip_writer_init_v2(pZip, 0, flags)) + if(!mz_zip_writer_init_v2(pZip, 0, flags)) return MZ_FALSE; pZip->m_pState->m_pFile = pFile; @@ -5376,49 +5376,49 @@ mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFil { mz_zip_internal_state *pState; - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) + if((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - if (flags & MZ_ZIP_FLAG_WRITE_ZIP64) + if(flags & MZ_ZIP_FLAG_WRITE_ZIP64) { /* We don't support converting a non-zip64 file to zip64 - this seems like more trouble than it's worth. (What about the existing 32-bit data descriptors that could follow the compressed data?) */ - if (!pZip->m_pState->m_zip64) + if(!pZip->m_pState->m_zip64) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); } /* No sense in trying to write to an archive that's already at the support max size */ - if (pZip->m_pState->m_zip64) + if(pZip->m_pState->m_zip64) { - if (pZip->m_total_files == MZ_UINT32_MAX) + if(pZip->m_total_files == MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); } else { - if (pZip->m_total_files == MZ_UINT16_MAX) + if(pZip->m_total_files == MZ_UINT16_MAX) return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); - if ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX) + if((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE); } pState = pZip->m_pState; - if (pState->m_pFile) + if(pState->m_pFile) { #ifdef MINIZ_NO_STDIO (void)pFilename; return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); #else - if (pZip->m_pIO_opaque != pZip) + if(pZip->m_pIO_opaque != pZip) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE) + if(pZip->m_zip_type == MZ_ZIP_TYPE_FILE) { - if (!pFilename) + if(!pFilename) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); /* Archive is being read from stdio and was originally opened only for reading. Try to reopen as writable. */ - if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) + if(NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) { /* The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. */ mz_zip_reader_end_internal(pZip, MZ_FALSE); @@ -5429,17 +5429,17 @@ mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFil pZip->m_pWrite = mz_zip_file_write_func; #endif /* #ifdef MINIZ_NO_STDIO */ } - else if (pState->m_pMem) + else if(pState->m_pMem) { /* Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. */ - if (pZip->m_pIO_opaque != pZip) + if(pZip->m_pIO_opaque != pZip) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); pState->m_mem_capacity = pState->m_mem_size; pZip->m_pWrite = mz_zip_heap_write_func; } /* Archive is being read via a user provided read function - make sure the user has specified a write function too. */ - else if (!pZip->m_pWrite) + else if(!pZip->m_pWrite) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); /* Start writing new files at the archive's current central directory location. */ @@ -5478,7 +5478,7 @@ typedef struct static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len, void *pUser) { mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser; - if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len) + if((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len) return MZ_FALSE; pState->m_cur_archive_file_ofs += len; @@ -5498,21 +5498,21 @@ static mz_uint32 mz_zip_writer_create_zip64_extra_data(mz_uint8 *pBuf, mz_uint64 mz_uint32 field_size = 0; - if (pUncomp_size) + if(pUncomp_size) { MZ_WRITE_LE64(pDst, *pUncomp_size); pDst += sizeof(mz_uint64); field_size += sizeof(mz_uint64); } - if (pComp_size) + if(pComp_size) { MZ_WRITE_LE64(pDst, *pComp_size); pDst += sizeof(mz_uint64); field_size += sizeof(mz_uint64); } - if (pLocal_header_ofs) + if(pLocal_header_ofs) { MZ_WRITE_LE64(pDst, *pLocal_header_ofs); pDst += sizeof(mz_uint64); @@ -5579,20 +5579,20 @@ static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char size_t orig_central_dir_size = pState->m_central_dir.m_size; mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; - if (!pZip->m_pState->m_zip64) + if(!pZip->m_pState->m_zip64) { - if (local_header_ofs > 0xFFFFFFFF) + if(local_header_ofs > 0xFFFFFFFF) return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE); } /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */ - if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + user_extra_data_len + comment_size) >= MZ_UINT32_MAX) + if(((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + user_extra_data_len + comment_size) >= MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); - if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size + user_extra_data_len, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes)) + if(!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size + user_extra_data_len, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes)) return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) || + if((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) || (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) || (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) || (!mz_zip_array_push_back(pZip, &pState->m_central_dir, user_extra_data, user_extra_data_len)) || @@ -5610,12 +5610,12 @@ static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) { /* Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. */ - if (*pArchive_name == '/') + if(*pArchive_name == '/') return MZ_FALSE; - while (*pArchive_name) + while(*pArchive_name) { - if ((*pArchive_name == '\\') || (*pArchive_name == ':')) + if((*pArchive_name == '\\') || (*pArchive_name == ':')) return MZ_FALSE; pArchive_name++; @@ -5627,7 +5627,7 @@ static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) { mz_uint32 n; - if (!pZip->m_file_offset_alignment) + if(!pZip->m_file_offset_alignment) return 0; n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1)); return (mz_uint)((pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1)); @@ -5637,10 +5637,10 @@ static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_fil { char buf[4096]; memset(buf, 0, MZ_MIN(sizeof(buf), n)); - while (n) + while(n) { mz_uint32 s = MZ_MIN(sizeof(buf), n); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s) + if(pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s) return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); cur_file_ofs += s; @@ -5672,48 +5672,48 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE]; mz_uint16 bit_flags = 0; - if (uncomp_size || (buf_size && !(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) + if(uncomp_size || (buf_size && !(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) bit_flags |= MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR; - if (level_and_flags & MZ_ZIP_FLAG_UTF8_FILENAME) + if(level_and_flags & MZ_ZIP_FLAG_UTF8_FILENAME) bit_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8; - if ((int)level_and_flags < 0) + if((int)level_and_flags < 0) level_and_flags = MZ_DEFAULT_LEVEL; level = level_and_flags & 0xF; store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)); - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION)) + if((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); pState = pZip->m_pState; - if (pState->m_zip64) + if(pState->m_zip64) { - if (pZip->m_total_files == MZ_UINT32_MAX) + if(pZip->m_total_files == MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); } else { - if (pZip->m_total_files == MZ_UINT16_MAX) + if(pZip->m_total_files == MZ_UINT16_MAX) { pState->m_zip64 = MZ_TRUE; /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */ } - if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF)) + if((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF)) { pState->m_zip64 = MZ_TRUE; /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ } } - if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size)) + if((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - if (!mz_zip_writer_validate_archive_name(pArchive_name)) + if(!mz_zip_writer_validate_archive_name(pArchive_name)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME); - if (last_modified != NULL) + if(last_modified != NULL) { mz_zip_time_t_to_dos_time(*last_modified, &dos_time, &dos_date); } @@ -5729,53 +5729,53 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n } archive_name_size = strlen(pArchive_name); - if (archive_name_size > MZ_UINT16_MAX) + if(archive_name_size > MZ_UINT16_MAX) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME); num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */ - if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX) + if(((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); - if (!pState->m_zip64) + if(!pState->m_zip64) { /* Bail early if the archive would obviously become too large */ - if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF) + if((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF) { pState->m_zip64 = MZ_TRUE; /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ } } - if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) + if((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) { /* Set DOS Subdirectory attribute bit. */ ext_attributes |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG; /* Subdirectories cannot contain data. */ - if ((buf_size) || (uncomp_size)) + if((buf_size) || (uncomp_size)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); } /* Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) */ - if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + (pState->m_zip64 ? MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE : 0))) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1))) + if((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + (pState->m_zip64 ? MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE : 0))) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1))) return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - if ((!store_data_uncompressed) && (buf_size)) + if((!store_data_uncompressed) && (buf_size)) { - if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)))) + if(NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)))) return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); } - if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes)) + if(!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes)) { pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); return MZ_FALSE; } local_dir_header_ofs += num_alignment_padding_bytes; - if (pZip->m_file_offset_alignment) + if(pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } @@ -5783,38 +5783,38 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n MZ_CLEAR_OBJ(local_dir_header); - if (!store_data_uncompressed || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + if(!store_data_uncompressed || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) { method = MZ_DEFLATED; } - if (pState->m_zip64) + if(pState->m_zip64) { - if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX) + if(uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX) { pExtra_data = extra_data; extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); } - if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, extra_size + user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date)) + if(!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, extra_size + user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date)) return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + if(pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); cur_archive_file_ofs += sizeof(local_dir_header); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + if(pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) { pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); } cur_archive_file_ofs += archive_name_size; - if (pExtra_data != NULL) + if(pExtra_data != NULL) { - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size) + if(pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size) return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); cur_archive_file_ofs += extra_size; @@ -5822,17 +5822,17 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n } else { - if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX)) + if((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX)) return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); - if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date)) + if(!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date)) return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + if(pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); cur_archive_file_ofs += sizeof(local_dir_header); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + if(pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) { pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); @@ -5840,28 +5840,28 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n cur_archive_file_ofs += archive_name_size; } - if (user_extra_data_len > 0) + if(user_extra_data_len > 0) { - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len) + if(pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len) return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); cur_archive_file_ofs += user_extra_data_len; } - if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + if(!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) { uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size); uncomp_size = buf_size; - if (uncomp_size <= 3) + if(uncomp_size <= 3) { level = 0; store_data_uncompressed = MZ_TRUE; } } - if (store_data_uncompressed) + if(store_data_uncompressed) { - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size) + if(pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size) { pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); @@ -5870,7 +5870,7 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n cur_archive_file_ofs += buf_size; comp_size = buf_size; } - else if (buf_size) + else if(buf_size) { mz_zip_writer_add_state state; @@ -5878,7 +5878,7 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n state.m_cur_archive_file_ofs = cur_archive_file_ofs; state.m_comp_size = 0; - if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) || + if((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) || (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE)) { pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); @@ -5892,7 +5892,7 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); pComp = NULL; - if (uncomp_size) + if(uncomp_size) { MZ_ASSERT(bit_flags & MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR); @@ -5901,9 +5901,9 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID); MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32); - if (pExtra_data == NULL) + if(pExtra_data == NULL) { - if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX)) + if((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX)) return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); MZ_WRITE_LE32(local_dir_footer + 8, comp_size); @@ -5916,19 +5916,19 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64; } - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size) + if(pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size) return MZ_FALSE; cur_archive_file_ofs += local_dir_footer_size; } - if (pExtra_data != NULL) + if(pExtra_data != NULL) { extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); } - if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, extra_size, pComment, + if(!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, extra_size, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes, user_extra_data_central, user_extra_data_central_len)) return MZ_FALSE; @@ -5954,20 +5954,20 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE]; mz_zip_internal_state *pState; - if (level_and_flags & MZ_ZIP_FLAG_UTF8_FILENAME) + if(level_and_flags & MZ_ZIP_FLAG_UTF8_FILENAME) gen_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8; - if ((int)level_and_flags < 0) + if((int)level_and_flags < 0) level_and_flags = MZ_DEFAULT_LEVEL; level = level_and_flags & 0xF; /* Sanity checks */ - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION)) + if((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); pState = pZip->m_pState; - if ((!pState->m_zip64) && (uncomp_size > MZ_UINT32_MAX)) + if((!pState->m_zip64) && (uncomp_size > MZ_UINT32_MAX)) { /* Source file is too large for non-zip64 */ /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ @@ -5975,20 +5975,20 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, } /* We could support this, but why? */ - if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) + if(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - if (!mz_zip_writer_validate_archive_name(pArchive_name)) + if(!mz_zip_writer_validate_archive_name(pArchive_name)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME); - if (pState->m_zip64) + if(pState->m_zip64) { - if (pZip->m_total_files == MZ_UINT32_MAX) + if(pZip->m_total_files == MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); } else { - if (pZip->m_total_files == MZ_UINT16_MAX) + if(pZip->m_total_files == MZ_UINT16_MAX) { pState->m_zip64 = MZ_TRUE; /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */ @@ -5996,19 +5996,19 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, } archive_name_size = strlen(pArchive_name); - if (archive_name_size > MZ_UINT16_MAX) + if(archive_name_size > MZ_UINT16_MAX) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME); num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */ - if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX) + if(((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); - if (!pState->m_zip64) + if(!pState->m_zip64) { /* Bail early if the archive would obviously become too large */ - if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024) > 0xFFFFFFFF) + if((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024) > 0xFFFFFFFF) { pState->m_zip64 = MZ_TRUE; /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ @@ -6016,16 +6016,16 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, } #ifndef MINIZ_NO_TIME - if (pFile_time) + if(pFile_time) { mz_zip_time_t_to_dos_time(*pFile_time, &dos_time, &dos_date); } #endif - if (uncomp_size <= 3) + if(uncomp_size <= 3) level = 0; - if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes)) + if(!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes)) { return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); } @@ -6033,59 +6033,59 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, cur_archive_file_ofs += num_alignment_padding_bytes; local_dir_header_ofs = cur_archive_file_ofs; - if (pZip->m_file_offset_alignment) + if(pZip->m_file_offset_alignment) { MZ_ASSERT((cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } - if (uncomp_size && level) + if(uncomp_size && level) { method = MZ_DEFLATED; } MZ_CLEAR_OBJ(local_dir_header); - if (pState->m_zip64) + if(pState->m_zip64) { - if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX) + if(uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX) { pExtra_data = extra_data; extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); } - if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, extra_size + user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date)) + if(!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, extra_size + user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date)) return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + if(pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); cur_archive_file_ofs += sizeof(local_dir_header); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + if(pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) { return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); } cur_archive_file_ofs += archive_name_size; - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size) + if(pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size) return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); cur_archive_file_ofs += extra_size; } else { - if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX)) + if((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX)) return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); - if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date)) + if(!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date)) return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + if(pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); cur_archive_file_ofs += sizeof(local_dir_header); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + if(pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) { return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); } @@ -6093,29 +6093,29 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, cur_archive_file_ofs += archive_name_size; } - if (user_extra_data_len > 0) + if(user_extra_data_len > 0) { - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len) + if(pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len) return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); cur_archive_file_ofs += user_extra_data_len; } - if (uncomp_size) + if(uncomp_size) { mz_uint64 uncomp_remaining = uncomp_size; void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE); - if (!pRead_buf) + if(!pRead_buf) { return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); } - if (!level) + if(!level) { - while (uncomp_remaining) + while(uncomp_remaining) { mz_uint n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining); - if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)) + if((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)) { pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); @@ -6131,7 +6131,7 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, mz_bool result = MZ_FALSE; mz_zip_writer_add_state state; tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)); - if (!pComp) + if(!pComp) { pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); @@ -6141,19 +6141,19 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, state.m_cur_archive_file_ofs = cur_archive_file_ofs; state.m_comp_size = 0; - if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) + if(tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) { pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); } - for (;;) + for(;;) { size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE); tdefl_status status; - if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size) + if(MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size) { mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); break; @@ -6163,12 +6163,12 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, uncomp_remaining -= in_buf_size; status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH); - if (status == TDEFL_STATUS_DONE) + if(status == TDEFL_STATUS_DONE) { result = MZ_TRUE; break; } - else if (status != TDEFL_STATUS_OKAY) + else if(status != TDEFL_STATUS_OKAY) { mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED); break; @@ -6177,7 +6177,7 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - if (!result) + if(!result) { pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); return MZ_FALSE; @@ -6195,9 +6195,9 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID); MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32); - if (pExtra_data == NULL) + if(pExtra_data == NULL) { - if (comp_size > MZ_UINT32_MAX) + if(comp_size > MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); MZ_WRITE_LE32(local_dir_footer + 8, comp_size); @@ -6210,18 +6210,18 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64; } - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size) + if(pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size) return MZ_FALSE; cur_archive_file_ofs += local_dir_footer_size; - if (pExtra_data != NULL) + if(pExtra_data != NULL) { extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); } - if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, extra_size, pComment, comment_size, + if(!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, extra_size, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, gen_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes, user_extra_data_central, user_extra_data_central_len)) return MZ_FALSE; @@ -6243,12 +6243,12 @@ mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO) pFile_time = &file_modified_time; - if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time)) + if(!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time)) return mz_zip_set_error(pZip, MZ_ZIP_FILE_STAT_FAILED); #endif pSrc_file = MZ_FOPEN(pSrc_filename, "rb"); - if (!pSrc_file) + if(!pSrc_file) return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); MZ_FSEEK64(pSrc_file, 0, SEEK_END); @@ -6266,12 +6266,12 @@ mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, static mz_bool mz_zip_writer_update_zip64_extension_block(mz_zip_array *pNew_ext, mz_zip_archive *pZip, const mz_uint8 *pExt, uint32_t ext_len, mz_uint64 *pComp_size, mz_uint64 *pUncomp_size, mz_uint64 *pLocal_header_ofs, mz_uint32 *pDisk_start) { /* + 64 should be enough for any new zip64 data */ - if (!mz_zip_array_reserve(pZip, pNew_ext, ext_len + 64, MZ_FALSE)) + if(!mz_zip_array_reserve(pZip, pNew_ext, ext_len + 64, MZ_FALSE)) return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); mz_zip_array_resize(pZip, pNew_ext, 0, MZ_FALSE); - if ((pUncomp_size) || (pComp_size) || (pLocal_header_ofs) || (pDisk_start)) + if((pUncomp_size) || (pComp_size) || (pLocal_header_ofs) || (pDisk_start)) { mz_uint8 new_ext_block[64]; mz_uint8 *pDst = new_ext_block; @@ -6279,25 +6279,25 @@ static mz_bool mz_zip_writer_update_zip64_extension_block(mz_zip_array *pNew_ext mz_write_le16(pDst + sizeof(mz_uint16), 0); pDst += sizeof(mz_uint16) * 2; - if (pUncomp_size) + if(pUncomp_size) { mz_write_le64(pDst, *pUncomp_size); pDst += sizeof(mz_uint64); } - if (pComp_size) + if(pComp_size) { mz_write_le64(pDst, *pComp_size); pDst += sizeof(mz_uint64); } - if (pLocal_header_ofs) + if(pLocal_header_ofs) { mz_write_le64(pDst, *pLocal_header_ofs); pDst += sizeof(mz_uint64); } - if (pDisk_start) + if(pDisk_start) { mz_write_le32(pDst, *pDisk_start); pDst += sizeof(mz_uint32); @@ -6305,11 +6305,11 @@ static mz_bool mz_zip_writer_update_zip64_extension_block(mz_zip_array *pNew_ext mz_write_le16(new_ext_block + sizeof(mz_uint16), (mz_uint16)((pDst - new_ext_block) - sizeof(mz_uint16) * 2)); - if (!mz_zip_array_push_back(pZip, pNew_ext, new_ext_block, pDst - new_ext_block)) + if(!mz_zip_array_push_back(pZip, pNew_ext, new_ext_block, pDst - new_ext_block)) return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); } - if ((pExt) && (ext_len)) + if((pExt) && (ext_len)) { mz_uint32 extra_size_remaining = ext_len; const mz_uint8 *pExtra_data = pExt; @@ -6318,25 +6318,25 @@ static mz_bool mz_zip_writer_update_zip64_extension_block(mz_zip_array *pNew_ext { mz_uint32 field_id, field_data_size, field_total_size; - if (extra_size_remaining < (sizeof(mz_uint16) * 2)) + if(extra_size_remaining < (sizeof(mz_uint16) * 2)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); field_id = MZ_READ_LE16(pExtra_data); field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); field_total_size = field_data_size + sizeof(mz_uint16) * 2; - if (field_total_size > extra_size_remaining) + if(field_total_size > extra_size_remaining) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - if (field_id != MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) + if(field_id != MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) { - if (!mz_zip_array_push_back(pZip, pNew_ext, pExtra_data, field_total_size)) + if(!mz_zip_array_push_back(pZip, pNew_ext, pExtra_data, field_total_size)) return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); } pExtra_data += field_total_size; extra_size_remaining -= field_total_size; - } while (extra_size_remaining); + } while(extra_size_remaining); } return MZ_TRUE; @@ -6362,20 +6362,20 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive * mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE; /* Sanity checks */ - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pSource_zip->m_pRead)) + if((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pSource_zip->m_pRead)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); pState = pZip->m_pState; /* Don't support copying files from zip64 archives to non-zip64, even though in some cases this is possible */ - if ((pSource_zip->m_pState->m_zip64) && (!pZip->m_pState->m_zip64)) + if((pSource_zip->m_pState->m_zip64) && (!pZip->m_pState->m_zip64)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); /* Get pointer to the source central dir header and crack it */ - if (NULL == (pSrc_central_header = mz_zip_get_cdh(pSource_zip, src_file_index))) + if(NULL == (pSrc_central_header = mz_zip_get_cdh(pSource_zip, src_file_index))) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - if (MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_SIG_OFS) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG) + if(MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_SIG_OFS) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); src_filename_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS); @@ -6384,34 +6384,34 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive * src_central_dir_following_data_size = src_filename_len + src_ext_len + src_comment_len; /* TODO: We don't support central dir's >= MZ_UINT32_MAX bytes right now (+32 fudge factor in case we need to add more extra data) */ - if ((pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + 32) >= MZ_UINT32_MAX) + if((pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + 32) >= MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); - if (!pState->m_zip64) + if(!pState->m_zip64) { - if (pZip->m_total_files == MZ_UINT16_MAX) + if(pZip->m_total_files == MZ_UINT16_MAX) return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); } else { /* TODO: Our zip64 support still has some 32-bit limits that may not be worth fixing. */ - if (pZip->m_total_files == MZ_UINT32_MAX) + if(pZip->m_total_files == MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); } - if (!mz_zip_file_stat_internal(pSource_zip, src_file_index, pSrc_central_header, &src_file_stat, NULL)) + if(!mz_zip_file_stat_internal(pSource_zip, src_file_index, pSrc_central_header, &src_file_stat, NULL)) return MZ_FALSE; cur_src_file_ofs = src_file_stat.m_local_header_ofs; cur_dst_file_ofs = pZip->m_archive_size; /* Read the source archive's local dir header */ - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + if(pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + if(MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; @@ -6424,16 +6424,16 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive * src_archive_bytes_remaining = local_header_filename_size + local_header_extra_len + src_file_stat.m_comp_size; /* Try to find a zip64 extended information field */ - if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX))) + if((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX))) { mz_zip_array file_data_array; mz_zip_array_init(&file_data_array, 1); - if (!mz_zip_array_resize(pZip, &file_data_array, local_header_extra_len, MZ_FALSE)) + if(!mz_zip_array_resize(pZip, &file_data_array, local_header_extra_len, MZ_FALSE)) { return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); } - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, src_file_stat.m_local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_size, file_data_array.m_p, local_header_extra_len) != local_header_extra_len) + if(pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, src_file_stat.m_local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_size, file_data_array.m_p, local_header_extra_len) != local_header_extra_len) { mz_zip_array_clear(pZip, &file_data_array); return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); @@ -6446,7 +6446,7 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive * { mz_uint32 field_id, field_data_size, field_total_size; - if (extra_size_remaining < (sizeof(mz_uint16) * 2)) + if(extra_size_remaining < (sizeof(mz_uint16) * 2)) { mz_zip_array_clear(pZip, &file_data_array); return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); @@ -6456,17 +6456,17 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive * field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); field_total_size = field_data_size + sizeof(mz_uint16) * 2; - if (field_total_size > extra_size_remaining) + if(field_total_size > extra_size_remaining) { mz_zip_array_clear(pZip, &file_data_array); return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); } - if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) + if(field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) { const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32); - if (field_data_size < sizeof(mz_uint64) * 2) + if(field_data_size < sizeof(mz_uint64) * 2) { mz_zip_array_clear(pZip, &file_data_array); return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); @@ -6481,55 +6481,55 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive * pExtra_data += field_total_size; extra_size_remaining -= field_total_size; - } while (extra_size_remaining); + } while(extra_size_remaining); mz_zip_array_clear(pZip, &file_data_array); } - if (!pState->m_zip64) + if(!pState->m_zip64) { /* Try to detect if the new archive will most likely wind up too big and bail early (+(sizeof(mz_uint32) * 4) is for the optional descriptor which could be present, +64 is a fudge factor). */ /* We also check when the archive is finalized so this doesn't need to be perfect. */ mz_uint64 approx_new_archive_size = cur_dst_file_ofs + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + src_archive_bytes_remaining + (sizeof(mz_uint32) * 4) + pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 64; - if (approx_new_archive_size >= MZ_UINT32_MAX) + if(approx_new_archive_size >= MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); } /* Write dest archive padding */ - if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes)) + if(!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes)) return MZ_FALSE; cur_dst_file_ofs += num_alignment_padding_bytes; local_dir_header_ofs = cur_dst_file_ofs; - if (pZip->m_file_offset_alignment) + if(pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } /* The original zip's local header+ext block doesn't change, even with zip64, so we can just copy it over to the dest zip */ - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + if(pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; /* Copy over the source archive bytes to the dest archive, also ensure we have enough buf space to handle optional data descriptor */ - if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(32U, MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining))))) + if(NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(32U, MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining))))) return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - while (src_archive_bytes_remaining) + while(src_archive_bytes_remaining) { n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining); - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n) + if(pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n) { pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); } cur_src_file_ofs += n; - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) + if(pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) { pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); @@ -6541,19 +6541,19 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive * /* Now deal with the optional data descriptor */ bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS); - if (bit_flags & 8) + if(bit_flags & 8) { /* Copy data descriptor */ - if ((pSource_zip->m_pState->m_zip64) || (found_zip64_ext_data_in_ldir)) + if((pSource_zip->m_pState->m_zip64) || (found_zip64_ext_data_in_ldir)) { /* src is zip64, dest must be zip64 */ - /* name uint32_t's */ - /* id 1 (optional in zip64?) */ - /* crc 1 */ - /* comp_size 2 */ + /* name uint32_t's */ + /* id 1 (optional in zip64?) */ + /* crc 1 */ + /* comp_size 2 */ /* uncomp_size 2 */ - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, (sizeof(mz_uint32) * 6)) != (sizeof(mz_uint32) * 6)) + if(pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, (sizeof(mz_uint32) * 6)) != (sizeof(mz_uint32) * 6)) { pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); @@ -6566,7 +6566,7 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive * /* src is NOT zip64 */ mz_bool has_id; - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) + if(pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) { pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); @@ -6574,7 +6574,7 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive * has_id = (MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID); - if (pZip->m_pState->m_zip64) + if(pZip->m_pState->m_zip64) { /* dest is zip64, so upgrade the data descriptor */ const mz_uint32 *pSrc_descriptor = (const mz_uint32 *)((const mz_uint8 *)pBuf + (has_id ? sizeof(mz_uint32) : 0)); @@ -6596,7 +6596,7 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive * } } - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) + if(pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) { pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); @@ -6612,7 +6612,7 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive * memcpy(new_central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); - if (pState->m_zip64) + if(pState->m_zip64) { /* This is the painful part: We need to write a new central dir header + ext block with updated zip64 fields, and ensure the old fields (if any) are not included. */ const mz_uint8 *pSrc_ext = pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len; @@ -6624,7 +6624,7 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive * MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_UINT32_MAX); MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_UINT32_MAX); - if (!mz_zip_writer_update_zip64_extension_block(&new_ext_block, pZip, pSrc_ext, src_ext_len, &src_file_stat.m_comp_size, &src_file_stat.m_uncomp_size, &local_dir_header_ofs, NULL)) + if(!mz_zip_writer_update_zip64_extension_block(&new_ext_block, pZip, pSrc_ext, src_ext_len, &src_file_stat.m_comp_size, &src_file_stat.m_uncomp_size, &local_dir_header_ofs, NULL)) { mz_zip_array_clear(pZip, &new_ext_block); return MZ_FALSE; @@ -6632,27 +6632,27 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive * MZ_WRITE_LE16(new_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS, new_ext_block.m_size); - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) + if(!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) { mz_zip_array_clear(pZip, &new_ext_block); return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); } - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_filename_len)) + if(!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_filename_len)) { mz_zip_array_clear(pZip, &new_ext_block); mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); } - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_ext_block.m_p, new_ext_block.m_size)) + if(!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_ext_block.m_p, new_ext_block.m_size)) { mz_zip_array_clear(pZip, &new_ext_block); mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); } - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len + src_ext_len, src_comment_len)) + if(!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len + src_ext_len, src_comment_len)) { mz_zip_array_clear(pZip, &new_ext_block); mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); @@ -6664,18 +6664,18 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive * else { /* sanity checks */ - if (cur_dst_file_ofs > MZ_UINT32_MAX) + if(cur_dst_file_ofs > MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); - if (local_dir_header_ofs >= MZ_UINT32_MAX) + if(local_dir_header_ofs >= MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs); - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) + if(!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_central_dir_following_data_size)) + if(!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_central_dir_following_data_size)) { mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); @@ -6683,7 +6683,7 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive * } /* This shouldn't trigger unless we screwed up during the initial sanity checks */ - if (pState->m_central_dir.m_size >= MZ_UINT32_MAX) + if(pState->m_central_dir.m_size >= MZ_UINT32_MAX) { /* TODO: Support central dirs >= 32-bits in size */ mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); @@ -6691,7 +6691,7 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive * } n = (mz_uint32)orig_central_dir_size; - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) + if(!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) { mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); @@ -6709,37 +6709,37 @@ mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) mz_uint64 central_dir_ofs, central_dir_size; mz_uint8 hdr[256]; - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) + if((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); pState = pZip->m_pState; - if (pState->m_zip64) + if(pState->m_zip64) { - if ((pZip->m_total_files > MZ_UINT32_MAX) || (pState->m_central_dir.m_size >= MZ_UINT32_MAX)) + if((pZip->m_total_files > MZ_UINT32_MAX) || (pState->m_central_dir.m_size >= MZ_UINT32_MAX)) return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); } else { - if ((pZip->m_total_files > MZ_UINT16_MAX) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX)) + if((pZip->m_total_files > MZ_UINT16_MAX) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX)) return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); } central_dir_ofs = 0; central_dir_size = 0; - if (pZip->m_total_files) + if(pZip->m_total_files) { /* Write central directory */ central_dir_ofs = pZip->m_archive_size; central_dir_size = pState->m_central_dir.m_size; pZip->m_central_directory_file_ofs = central_dir_ofs; - if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size) + if(pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size) return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); pZip->m_archive_size += central_dir_size; } - if (pState->m_zip64) + if(pState->m_zip64) { /* Write zip64 end of central directory header */ mz_uint64 rel_ofs_to_zip64_ecdr = pZip->m_archive_size; @@ -6753,7 +6753,7 @@ mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files); MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_SIZE_OFS, central_dir_size); MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_OFS_OFS, central_dir_ofs); - if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) + if(pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE; @@ -6763,7 +6763,7 @@ mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG); MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS, rel_ofs_to_zip64_ecdr); MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS, 1); - if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) + if(pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE; @@ -6777,11 +6777,11 @@ mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_size)); MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_ofs)); - if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + if(pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); #ifndef MINIZ_NO_STDIO - if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF)) + if((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF)) return mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED); #endif /* #ifndef MINIZ_NO_STDIO */ @@ -6793,19 +6793,19 @@ mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf, size_t *pSize) { - if ((!ppBuf) || (!pSize)) + if((!ppBuf) || (!pSize)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); *ppBuf = NULL; *pSize = 0; - if ((!pZip) || (!pZip->m_pState)) + if((!pZip) || (!pZip->m_pState)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - if (pZip->m_pWrite != mz_zip_heap_write_func) + if(pZip->m_pWrite != mz_zip_heap_write_func) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - if (!mz_zip_writer_finalize_archive(pZip)) + if(!mz_zip_writer_finalize_archive(pZip)) return MZ_FALSE; *ppBuf = pZip->m_pState->m_pMem; @@ -6835,31 +6835,31 @@ mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, co mz_zip_error actual_err = MZ_ZIP_NO_ERROR; mz_zip_zero_struct(&zip_archive); - if ((int)level_and_flags < 0) + if((int)level_and_flags < 0) level_and_flags = MZ_DEFAULT_LEVEL; - if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION)) + if((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION)) { - if (pErr) + if(pErr) *pErr = MZ_ZIP_INVALID_PARAMETER; return MZ_FALSE; } - if (!mz_zip_writer_validate_archive_name(pArchive_name)) + if(!mz_zip_writer_validate_archive_name(pArchive_name)) { - if (pErr) + if(pErr) *pErr = MZ_ZIP_INVALID_FILENAME; return MZ_FALSE; } /* Important: The regular non-64 bit version of stat() can fail here if the file is very large, which could cause the archive to be overwritten. */ /* So be sure to compile with _LARGEFILE64_SOURCE 1 */ - if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) + if(MZ_FILE_STAT(pZip_filename, &file_stat) != 0) { /* Create a new archive. */ - if (!mz_zip_writer_init_file_v2(&zip_archive, pZip_filename, 0, level_and_flags)) + if(!mz_zip_writer_init_file_v2(&zip_archive, pZip_filename, 0, level_and_flags)) { - if (pErr) + if(pErr) *pErr = zip_archive.m_last_error; return MZ_FALSE; } @@ -6869,16 +6869,16 @@ mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, co else { /* Append to an existing archive. */ - if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0)) + if(!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0)) { - if (pErr) + if(pErr) *pErr = zip_archive.m_last_error; return MZ_FALSE; } - if (!mz_zip_writer_init_from_reader_v2(&zip_archive, pZip_filename, level_and_flags)) + if(!mz_zip_writer_init_from_reader_v2(&zip_archive, pZip_filename, level_and_flags)) { - if (pErr) + if(pErr) *pErr = zip_archive.m_last_error; mz_zip_reader_end_internal(&zip_archive, MZ_FALSE); @@ -6891,30 +6891,30 @@ mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, co actual_err = zip_archive.m_last_error; /* Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) */ - if (!mz_zip_writer_finalize_archive(&zip_archive)) + if(!mz_zip_writer_finalize_archive(&zip_archive)) { - if (!actual_err) + if(!actual_err) actual_err = zip_archive.m_last_error; status = MZ_FALSE; } - if (!mz_zip_writer_end_internal(&zip_archive, status)) + if(!mz_zip_writer_end_internal(&zip_archive, status)) { - if (!actual_err) + if(!actual_err) actual_err = zip_archive.m_last_error; status = MZ_FALSE; } - if ((!status) && (created_new_archive)) + if((!status) && (created_new_archive)) { /* It's a new archive and something went wrong, so just delete it. */ int ignoredStatus = MZ_DELETE_FILE(pZip_filename); (void)ignoredStatus; } - if (pErr) + if(pErr) *pErr = actual_err; return status; @@ -6926,34 +6926,34 @@ void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const ch mz_zip_archive zip_archive; void *p = NULL; - if (pSize) + if(pSize) *pSize = 0; - if ((!pZip_filename) || (!pArchive_name)) + if((!pZip_filename) || (!pArchive_name)) { - if (pErr) + if(pErr) *pErr = MZ_ZIP_INVALID_PARAMETER; return NULL; } mz_zip_zero_struct(&zip_archive); - if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0)) + if(!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0)) { - if (pErr) + if(pErr) *pErr = zip_archive.m_last_error; return NULL; } - if (mz_zip_reader_locate_file_v2(&zip_archive, pArchive_name, pComment, flags, &file_index)) + if(mz_zip_reader_locate_file_v2(&zip_archive, pArchive_name, pComment, flags, &file_index)) { p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags); } mz_zip_reader_end_internal(&zip_archive, p != NULL); - if (pErr) + if(pErr) *pErr = zip_archive.m_last_error; return p; @@ -6984,7 +6984,7 @@ mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num) { mz_zip_error prev_err; - if (!pZip) + if(!pZip) return MZ_ZIP_INVALID_PARAMETER; prev_err = pZip->m_last_error; @@ -6995,7 +6995,7 @@ mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num) mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip) { - if (!pZip) + if(!pZip) return MZ_ZIP_INVALID_PARAMETER; return pZip->m_last_error; @@ -7010,7 +7010,7 @@ mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip) { mz_zip_error prev_err; - if (!pZip) + if(!pZip) return MZ_ZIP_INVALID_PARAMETER; prev_err = pZip->m_last_error; @@ -7021,7 +7021,7 @@ mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip) const char *mz_zip_get_error_string(mz_zip_error mz_err) { - switch (mz_err) + switch(mz_err) { case MZ_ZIP_NO_ERROR: return "no error"; @@ -7097,7 +7097,7 @@ const char *mz_zip_get_error_string(mz_zip_error mz_err) /* Note: Just because the archive is not zip64 doesn't necessarily mean it doesn't have Zip64 extended information extra field, argh. */ mz_bool mz_zip_is_zip64(mz_zip_archive *pZip) { - if ((!pZip) || (!pZip->m_pState)) + if((!pZip) || (!pZip->m_pState)) return MZ_FALSE; return pZip->m_pState->m_zip64; @@ -7105,7 +7105,7 @@ mz_bool mz_zip_is_zip64(mz_zip_archive *pZip) size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip) { - if ((!pZip) || (!pZip->m_pState)) + if((!pZip) || (!pZip->m_pState)) return 0; return pZip->m_pState->m_central_dir.m_size; @@ -7118,28 +7118,28 @@ mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip) { - if (!pZip) + if(!pZip) return 0; return pZip->m_archive_size; } mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip) { - if ((!pZip) || (!pZip->m_pState)) + if((!pZip) || (!pZip->m_pState)) return 0; return pZip->m_pState->m_file_archive_start_ofs; } MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip) { - if ((!pZip) || (!pZip->m_pState)) + if((!pZip) || (!pZip->m_pState)) return 0; return pZip->m_pState->m_pFile; } size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n) { - if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pZip->m_pRead)) + if((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pZip->m_pRead)) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); return pZip->m_pRead(pZip->m_pIO_opaque, file_ofs, pBuf, n); @@ -7149,15 +7149,15 @@ mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, cha { mz_uint n; const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index); - if (!p) + if(!p) { - if (filename_buf_size) + if(filename_buf_size) pFilename[0] = '\0'; mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); return 0; } n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); - if (filename_buf_size) + if(filename_buf_size) { n = MZ_MIN(n, filename_buf_size - 1); memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); @@ -7173,12 +7173,12 @@ mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip mz_bool mz_zip_end(mz_zip_archive *pZip) { - if (!pZip) + if(!pZip) return MZ_FALSE; - if (pZip->m_zip_mode == MZ_ZIP_MODE_READING) + if(pZip->m_zip_mode == MZ_ZIP_MODE_READING) return mz_zip_reader_end(pZip); - else if ((pZip->m_zip_mode == MZ_ZIP_MODE_WRITING) || (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)) + else if((pZip->m_zip_mode == MZ_ZIP_MODE_WRITING) || (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)) return mz_zip_writer_end(pZip); return MZ_FALSE; diff --git a/src/miniz/miniz.h b/src/miniz/miniz.h index 6353d3782b2..0f75976248f 100644 --- a/src/miniz/miniz.h +++ b/src/miniz/miniz.h @@ -540,9 +540,9 @@ typedef bool mz_bool; /* Works around MSVC's spammy "warning C4127: conditional expression is constant" message. */ #ifdef _MSC_VER -#define MZ_MACRO_END while (0, 0) +#define MZ_MACRO_END while(0, 0) #else -#define MZ_MACRO_END while (0) +#define MZ_MACRO_END while(0) #endif #ifdef MINIZ_NO_STDIO @@ -1241,13 +1241,13 @@ mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pA #if 0 /* TODO */ - typedef void *mz_zip_streaming_extract_state_ptr; - mz_zip_streaming_extract_state_ptr mz_zip_streaming_extract_begin(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags); - uint64_t mz_zip_streaming_extract_get_size(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); - uint64_t mz_zip_streaming_extract_get_cur_ofs(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); - mz_bool mz_zip_streaming_extract_seek(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, uint64_t new_ofs); - size_t mz_zip_streaming_extract_read(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, void *pBuf, size_t buf_size); - mz_bool mz_zip_streaming_extract_end(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); + typedef void *mz_zip_streaming_extract_state_ptr; + mz_zip_streaming_extract_state_ptr mz_zip_streaming_extract_begin(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags); + uint64_t mz_zip_streaming_extract_get_size(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); + uint64_t mz_zip_streaming_extract_get_cur_ofs(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); + mz_bool mz_zip_streaming_extract_seek(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, uint64_t new_ofs); + size_t mz_zip_streaming_extract_read(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, void *pBuf, size_t buf_size); + mz_bool mz_zip_streaming_extract_end(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); #endif /* This function compares the archive's local headers, the optional local zip64 extended information block, and the optional descriptor following the compressed data vs. the data in the central directory. */ From 7d73d66f17de3179c81738f713dbb344273aed69 Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Tue, 7 Mar 2017 19:30:12 -0800 Subject: [PATCH 097/699] libzip/zlib download no longer needed --- COMPILING | 4 ---- 1 file changed, 4 deletions(-) diff --git a/COMPILING b/COMPILING index 13b8339abd7..60579fe9f3b 100644 --- a/COMPILING +++ b/COMPILING @@ -48,8 +48,6 @@ We assume that you have a Debian/Ubuntu or Red Hat-like distribution. cd cbmc-git/src make minisat2-download - make libzip-download zlib-download - make libzip-build make @@ -126,8 +124,6 @@ Follow these instructions: cd cbmc-git/src make minisat2-download - make libzip-download zlib-download - make libzip-build make From f430ec5a4f839d9c67f6ecdb1fdb2992b278ac24 Mon Sep 17 00:00:00 2001 From: Pascal Kesseli Date: Wed, 8 Mar 2017 15:12:37 +0000 Subject: [PATCH 098/699] Fixed compilation issues on MinGW Added missing includes which caused compilation errors on MinGW 5.3.0. --- src/cegis/cegis-util/cbmc_runner.cpp | 2 ++ src/cegis/genetic/dynamic_test_runner_helper.cpp | 1 + src/cegis/jsa/learn/extract_candidate.cpp | 2 ++ 3 files changed, 5 insertions(+) diff --git a/src/cegis/cegis-util/cbmc_runner.cpp b/src/cegis/cegis-util/cbmc_runner.cpp index 58739658ab1..1d30bbfa63e 100644 --- a/src/cegis/cegis-util/cbmc_runner.cpp +++ b/src/cegis/cegis-util/cbmc_runner.cpp @@ -7,6 +7,8 @@ Author: Daniel Kroening, kroening@kroening.com \*******************************************************************/ +#include + #include #include diff --git a/src/cegis/genetic/dynamic_test_runner_helper.cpp b/src/cegis/genetic/dynamic_test_runner_helper.cpp index f357b80b72d..bb3de1236d5 100644 --- a/src/cegis/genetic/dynamic_test_runner_helper.cpp +++ b/src/cegis/genetic/dynamic_test_runner_helper.cpp @@ -12,6 +12,7 @@ Author: Daniel Kroening, kroening@kroening.com #endif #include +#include #include #include diff --git a/src/cegis/jsa/learn/extract_candidate.cpp b/src/cegis/jsa/learn/extract_candidate.cpp index 40ed53af0b2..0a27a48c2bd 100644 --- a/src/cegis/jsa/learn/extract_candidate.cpp +++ b/src/cegis/jsa/learn/extract_candidate.cpp @@ -7,6 +7,8 @@ Author: Daniel Kroening, kroening@kroening.com \*******************************************************************/ +#include + #include #include #include From 6861a5826d9dd2d4c1d0ce68c9d6d64fb3e0414a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Thu, 9 Mar 2017 11:05:27 +0100 Subject: [PATCH 099/699] remove `` from unapproved headers in cpplint The reason for `` being discouraged seems to be a preference for an external library within Google: https://github.com/google/styleguide/issues/194 --- scripts/cpplint.py | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/cpplint.py b/scripts/cpplint.py index 7fdc937ecf5..3d457bb4113 100755 --- a/scripts/cpplint.py +++ b/scripts/cpplint.py @@ -6264,7 +6264,6 @@ def FlagCxx11Features(filename, clean_lines, linenum, error): 'thread', 'chrono', 'ratio', - 'regex', 'system_error', ): error(filename, linenum, 'build/c++11', 5, From 4d316064ccf97aa38c7bcc956019a376fbcf98ef Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 14 Dec 2016 11:22:40 +0000 Subject: [PATCH 100/699] Use remove_instanceof in driver programs This adds a remove_instanceof call wherever there was an existing remove_virtual_functions call. --- src/cbmc/cbmc_parse_options.cpp | 2 +- src/goto-analyzer/goto_analyzer_parse_options.cpp | 2 +- src/symex/symex_parse_options.cpp | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/cbmc/cbmc_parse_options.cpp b/src/cbmc/cbmc_parse_options.cpp index 7364752d093..842b0b26f70 100644 --- a/src/cbmc/cbmc_parse_options.cpp +++ b/src/cbmc/cbmc_parse_options.cpp @@ -894,7 +894,7 @@ bool cbmc_parse_optionst::process_goto_program( cmdline.isset("pointer-check")); // Java virtual functions -> explicit dispatch tables: remove_virtual_functions(symbol_table, goto_functions); - // Java instanceof -> clsid comparison: + // Similar removal of RTTI inspection: remove_instanceof(symbol_table, goto_functions); // full slice? diff --git a/src/goto-analyzer/goto_analyzer_parse_options.cpp b/src/goto-analyzer/goto_analyzer_parse_options.cpp index 68e28755041..89d3d56731c 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.cpp +++ b/src/goto-analyzer/goto_analyzer_parse_options.cpp @@ -387,7 +387,7 @@ bool goto_analyzer_parse_optionst::process_goto_program( remove_function_pointers(goto_model, cmdline.isset("pointer-check")); // Java virtual functions -> explicit dispatch tables: remove_virtual_functions(goto_model); - // Java instanceof -> clsid comparison: + // remove rtti remove_instanceof(goto_model); // do partial inlining diff --git a/src/symex/symex_parse_options.cpp b/src/symex/symex_parse_options.cpp index 518e64a2ecd..2ed3fedc518 100644 --- a/src/symex/symex_parse_options.cpp +++ b/src/symex/symex_parse_options.cpp @@ -369,7 +369,6 @@ bool symex_parse_optionst::process_goto_program(const optionst &options) remove_vector(goto_model); // Java virtual functions -> explicit dispatch tables: remove_virtual_functions(goto_model); - // Java instanceof -> clsid comparison: remove_instanceof(goto_model); rewrite_union(goto_model); adjust_float_expressions(goto_model); From 206f7f4d6bb11cf6f6a8d25fdc597ecc6d2c93f2 Mon Sep 17 00:00:00 2001 From: Cristina Date: Wed, 8 Feb 2017 17:16:06 +0000 Subject: [PATCH 101/699] Added a side effect expr that pushes/pops Java try-catch handlers + irep ids for Java exception handling These are used to recreate Java try-catch contructs from bytecode. --- src/util/irep_ids.txt | 2 ++ src/util/std_code.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/util/irep_ids.txt b/src/util/irep_ids.txt index 29907f11040..dca7a814276 100644 --- a/src/util/irep_ids.txt +++ b/src/util/irep_ids.txt @@ -739,6 +739,8 @@ java_instanceof java_super_method_call skip_initialize java_enum_static_unwind +push_catch +handler string_constraint string_not_contains_constraint cprover_char_literal_func diff --git a/src/util/std_code.h b/src/util/std_code.h index 08aec694e9e..ed1f8f28b74 100644 --- a/src/util/std_code.h +++ b/src/util/std_code.h @@ -1122,6 +1122,36 @@ inline const side_effect_expr_throwt &to_side_effect_expr_throw( assert(expr.get(ID_statement)==ID_throw); return static_cast(expr); } +/*! \brief A side effect that pushes/pops a catch handler +*/ +class side_effect_expr_catcht:public side_effect_exprt +{ +public: + inline side_effect_expr_catcht():side_effect_exprt(ID_push_catch) + { + } + // TODO: change to ID_catch + inline explicit side_effect_expr_catcht(const irept &exception_list): + side_effect_exprt(ID_push_catch) + { + set(ID_exception_list, exception_list); + } +}; + +static inline side_effect_expr_catcht &to_side_effect_expr_catch(exprt &expr) +{ + assert(expr.id()==ID_side_effect); + assert(expr.get(ID_statement)==ID_push_catch); + return static_cast(expr); +} + +static inline const side_effect_expr_catcht &to_side_effect_expr_catch( + const exprt &expr) +{ + assert(expr.id()==ID_side_effect); + assert(expr.get(ID_statement)==ID_push_catch); + return static_cast(expr); +} /*! \brief A try/catch block */ From ebf9002e3c44c56ca866413390ff96c1d4cc2186 Mon Sep 17 00:00:00 2001 From: Cristina Date: Thu, 15 Dec 2016 09:42:25 +0000 Subject: [PATCH 102/699] Regression tests for exception handling --- regression/exceptions/Makefile | 14 +++++++ regression/exceptions/exceptions1/A.class | Bin 0 -> 234 bytes regression/exceptions/exceptions1/B.class | Bin 0 -> 216 bytes regression/exceptions/exceptions1/C.class | Bin 0 -> 216 bytes regression/exceptions/exceptions1/D.class | Bin 0 -> 216 bytes regression/exceptions/exceptions1/test.class | Bin 0 -> 1025 bytes regression/exceptions/exceptions1/test.desc | 10 +++++ regression/exceptions/exceptions1/test.java | 30 ++++++++++++++ regression/exceptions/exceptions10/A.class | Bin 0 -> 241 bytes regression/exceptions/exceptions10/B.class | Bin 0 -> 216 bytes regression/exceptions/exceptions10/C.class | Bin 0 -> 216 bytes regression/exceptions/exceptions10/test.class | Bin 0 -> 875 bytes regression/exceptions/exceptions10/test.desc | 9 ++++ regression/exceptions/exceptions10/test.java | 25 +++++++++++ regression/exceptions/exceptions11/A.class | Bin 0 -> 276 bytes regression/exceptions/exceptions11/B.class | Bin 0 -> 216 bytes regression/exceptions/exceptions11/test.class | Bin 0 -> 976 bytes regression/exceptions/exceptions11/test.desc | 9 ++++ regression/exceptions/exceptions11/test.java | 39 ++++++++++++++++++ regression/exceptions/exceptions12/A.class | Bin 0 -> 241 bytes regression/exceptions/exceptions12/B.class | Bin 0 -> 216 bytes regression/exceptions/exceptions12/C.class | Bin 0 -> 216 bytes regression/exceptions/exceptions12/F.class | Bin 0 -> 641 bytes regression/exceptions/exceptions12/test.class | Bin 0 -> 740 bytes regression/exceptions/exceptions12/test.desc | 9 ++++ regression/exceptions/exceptions12/test.java | 27 ++++++++++++ regression/exceptions/exceptions13/A.class | Bin 0 -> 241 bytes regression/exceptions/exceptions13/B.class | Bin 0 -> 216 bytes regression/exceptions/exceptions13/C.class | Bin 0 -> 216 bytes regression/exceptions/exceptions13/F.class | Bin 0 -> 405 bytes regression/exceptions/exceptions13/test.class | Bin 0 -> 740 bytes regression/exceptions/exceptions13/test.desc | 9 ++++ regression/exceptions/exceptions13/test.java | 28 +++++++++++++ regression/exceptions/exceptions14/A.class | Bin 0 -> 241 bytes regression/exceptions/exceptions14/B.class | Bin 0 -> 216 bytes regression/exceptions/exceptions14/C.class | Bin 0 -> 216 bytes regression/exceptions/exceptions14/test.class | Bin 0 -> 858 bytes regression/exceptions/exceptions14/test.desc | 8 ++++ regression/exceptions/exceptions14/test.java | 24 +++++++++++ regression/exceptions/exceptions2/A.class | Bin 0 -> 234 bytes regression/exceptions/exceptions2/B.class | Bin 0 -> 216 bytes regression/exceptions/exceptions2/C.class | Bin 0 -> 216 bytes regression/exceptions/exceptions2/test.class | Bin 0 -> 771 bytes regression/exceptions/exceptions2/test.desc | 10 +++++ regression/exceptions/exceptions2/test.java | 18 ++++++++ regression/exceptions/exceptions3/A.class | Bin 0 -> 234 bytes regression/exceptions/exceptions3/B.class | Bin 0 -> 216 bytes regression/exceptions/exceptions3/C.class | Bin 0 -> 216 bytes regression/exceptions/exceptions3/test.class | Bin 0 -> 751 bytes regression/exceptions/exceptions3/test.desc | 9 ++++ regression/exceptions/exceptions3/test.java | 17 ++++++++ regression/exceptions/exceptions4/A.class | Bin 0 -> 234 bytes regression/exceptions/exceptions4/B.class | Bin 0 -> 216 bytes regression/exceptions/exceptions4/C.class | Bin 0 -> 216 bytes regression/exceptions/exceptions4/test.class | Bin 0 -> 743 bytes regression/exceptions/exceptions4/test.desc | 8 ++++ regression/exceptions/exceptions4/test.java | 19 +++++++++ regression/exceptions/exceptions5/A.class | Bin 0 -> 234 bytes regression/exceptions/exceptions5/B.class | Bin 0 -> 216 bytes regression/exceptions/exceptions5/C.class | Bin 0 -> 216 bytes regression/exceptions/exceptions5/D.class | Bin 0 -> 216 bytes regression/exceptions/exceptions5/test.class | Bin 0 -> 997 bytes regression/exceptions/exceptions5/test.desc | 8 ++++ regression/exceptions/exceptions5/test.java | 27 ++++++++++++ regression/exceptions/exceptions6/A.class | Bin 0 -> 280 bytes regression/exceptions/exceptions6/B.class | Bin 0 -> 216 bytes regression/exceptions/exceptions6/C.class | Bin 0 -> 216 bytes regression/exceptions/exceptions6/D.class | Bin 0 -> 216 bytes regression/exceptions/exceptions6/test.class | Bin 0 -> 806 bytes regression/exceptions/exceptions6/test.desc | 9 ++++ regression/exceptions/exceptions6/test.java | 26 ++++++++++++ regression/exceptions/exceptions7/A.class | Bin 0 -> 241 bytes regression/exceptions/exceptions7/B.class | Bin 0 -> 216 bytes regression/exceptions/exceptions7/C.class | Bin 0 -> 216 bytes regression/exceptions/exceptions7/test.class | Bin 0 -> 871 bytes regression/exceptions/exceptions7/test.desc | 9 ++++ regression/exceptions/exceptions7/test.java | 25 +++++++++++ regression/exceptions/exceptions8/A.class | Bin 0 -> 241 bytes regression/exceptions/exceptions8/B.class | Bin 0 -> 216 bytes regression/exceptions/exceptions8/C.class | Bin 0 -> 216 bytes regression/exceptions/exceptions8/test.class | Bin 0 -> 935 bytes regression/exceptions/exceptions8/test.desc | 9 ++++ regression/exceptions/exceptions8/test.java | 29 +++++++++++++ regression/exceptions/exceptions9/A.class | Bin 0 -> 276 bytes regression/exceptions/exceptions9/B.class | Bin 0 -> 216 bytes regression/exceptions/exceptions9/C.class | Bin 0 -> 216 bytes regression/exceptions/exceptions9/test.class | Bin 0 -> 976 bytes regression/exceptions/exceptions9/test.desc | 8 ++++ regression/exceptions/exceptions9/test.java | 39 ++++++++++++++++++ 89 files changed, 511 insertions(+) create mode 100644 regression/exceptions/Makefile create mode 100644 regression/exceptions/exceptions1/A.class create mode 100644 regression/exceptions/exceptions1/B.class create mode 100644 regression/exceptions/exceptions1/C.class create mode 100644 regression/exceptions/exceptions1/D.class create mode 100644 regression/exceptions/exceptions1/test.class create mode 100644 regression/exceptions/exceptions1/test.desc create mode 100644 regression/exceptions/exceptions1/test.java create mode 100644 regression/exceptions/exceptions10/A.class create mode 100644 regression/exceptions/exceptions10/B.class create mode 100644 regression/exceptions/exceptions10/C.class create mode 100644 regression/exceptions/exceptions10/test.class create mode 100644 regression/exceptions/exceptions10/test.desc create mode 100644 regression/exceptions/exceptions10/test.java create mode 100644 regression/exceptions/exceptions11/A.class create mode 100644 regression/exceptions/exceptions11/B.class create mode 100644 regression/exceptions/exceptions11/test.class create mode 100644 regression/exceptions/exceptions11/test.desc create mode 100644 regression/exceptions/exceptions11/test.java create mode 100644 regression/exceptions/exceptions12/A.class create mode 100644 regression/exceptions/exceptions12/B.class create mode 100644 regression/exceptions/exceptions12/C.class create mode 100644 regression/exceptions/exceptions12/F.class create mode 100644 regression/exceptions/exceptions12/test.class create mode 100644 regression/exceptions/exceptions12/test.desc create mode 100644 regression/exceptions/exceptions12/test.java create mode 100644 regression/exceptions/exceptions13/A.class create mode 100644 regression/exceptions/exceptions13/B.class create mode 100644 regression/exceptions/exceptions13/C.class create mode 100644 regression/exceptions/exceptions13/F.class create mode 100644 regression/exceptions/exceptions13/test.class create mode 100644 regression/exceptions/exceptions13/test.desc create mode 100644 regression/exceptions/exceptions13/test.java create mode 100644 regression/exceptions/exceptions14/A.class create mode 100644 regression/exceptions/exceptions14/B.class create mode 100644 regression/exceptions/exceptions14/C.class create mode 100644 regression/exceptions/exceptions14/test.class create mode 100644 regression/exceptions/exceptions14/test.desc create mode 100644 regression/exceptions/exceptions14/test.java create mode 100644 regression/exceptions/exceptions2/A.class create mode 100644 regression/exceptions/exceptions2/B.class create mode 100644 regression/exceptions/exceptions2/C.class create mode 100644 regression/exceptions/exceptions2/test.class create mode 100644 regression/exceptions/exceptions2/test.desc create mode 100644 regression/exceptions/exceptions2/test.java create mode 100644 regression/exceptions/exceptions3/A.class create mode 100644 regression/exceptions/exceptions3/B.class create mode 100644 regression/exceptions/exceptions3/C.class create mode 100644 regression/exceptions/exceptions3/test.class create mode 100644 regression/exceptions/exceptions3/test.desc create mode 100644 regression/exceptions/exceptions3/test.java create mode 100644 regression/exceptions/exceptions4/A.class create mode 100644 regression/exceptions/exceptions4/B.class create mode 100644 regression/exceptions/exceptions4/C.class create mode 100644 regression/exceptions/exceptions4/test.class create mode 100644 regression/exceptions/exceptions4/test.desc create mode 100644 regression/exceptions/exceptions4/test.java create mode 100644 regression/exceptions/exceptions5/A.class create mode 100644 regression/exceptions/exceptions5/B.class create mode 100644 regression/exceptions/exceptions5/C.class create mode 100644 regression/exceptions/exceptions5/D.class create mode 100644 regression/exceptions/exceptions5/test.class create mode 100644 regression/exceptions/exceptions5/test.desc create mode 100644 regression/exceptions/exceptions5/test.java create mode 100644 regression/exceptions/exceptions6/A.class create mode 100644 regression/exceptions/exceptions6/B.class create mode 100644 regression/exceptions/exceptions6/C.class create mode 100644 regression/exceptions/exceptions6/D.class create mode 100644 regression/exceptions/exceptions6/test.class create mode 100644 regression/exceptions/exceptions6/test.desc create mode 100644 regression/exceptions/exceptions6/test.java create mode 100644 regression/exceptions/exceptions7/A.class create mode 100644 regression/exceptions/exceptions7/B.class create mode 100644 regression/exceptions/exceptions7/C.class create mode 100644 regression/exceptions/exceptions7/test.class create mode 100644 regression/exceptions/exceptions7/test.desc create mode 100644 regression/exceptions/exceptions7/test.java create mode 100644 regression/exceptions/exceptions8/A.class create mode 100644 regression/exceptions/exceptions8/B.class create mode 100644 regression/exceptions/exceptions8/C.class create mode 100644 regression/exceptions/exceptions8/test.class create mode 100644 regression/exceptions/exceptions8/test.desc create mode 100644 regression/exceptions/exceptions8/test.java create mode 100644 regression/exceptions/exceptions9/A.class create mode 100644 regression/exceptions/exceptions9/B.class create mode 100644 regression/exceptions/exceptions9/C.class create mode 100644 regression/exceptions/exceptions9/test.class create mode 100644 regression/exceptions/exceptions9/test.desc create mode 100644 regression/exceptions/exceptions9/test.java diff --git a/regression/exceptions/Makefile b/regression/exceptions/Makefile new file mode 100644 index 00000000000..5ac5a21995e --- /dev/null +++ b/regression/exceptions/Makefile @@ -0,0 +1,14 @@ +default: tests.log + +test: + @../test.pl -c ../../../src/cbmc/cbmc + +tests.log: ../test.pl + @../test.pl -c ../../../src/cbmc/cbmc + +show: + @for dir in *; do \ + if [ -d "$$dir" ]; then \ + vim -o "$$dir/*.java" "$$dir/*.out"; \ + fi; \ + done; diff --git a/regression/exceptions/exceptions1/A.class b/regression/exceptions/exceptions1/A.class new file mode 100644 index 0000000000000000000000000000000000000000..eb19ef6be2b4b0dc315cdfd2ae091ecc67882efd GIT binary patch literal 234 zcmXX=%MQU%5IsX5TBX7dSYn|YJ0fW$R*em@zv_l7)h5;QT~-ncAK;_J+%n0`dF0Gw z-k;|Szyuu^b+l}>ZTJLhrczbR3H8BnOE4DMUK0FBrE*oCcQW6IUBXT`%3_ghMXt2| zn?`X|7ha9RDZyQ5Wgg3=(s8GdmtuSpSK+~cNuZF>(>h2*dI&bhJiF;j=%dE}=pt^; iGFr?6M(voR2k6eE2Aii7D1o9M#q%+AiT z@6YoEV1a=P9X%U;8$Q8WsZ3RCf!TDLcb3PedAtLN)W> zG^(>I`7{ic1ox2FMIv{qi93}ntJy`|ga-pAfda+`BWV1+DPr)3*K{pl# WT<*@-G|^!l`~vXc^F-)=Q^5xrb|N0ia<-WNlvOJ0;V`m%{smNkcs&?*7 zqdu#OPor>6a1TXOrgEp+xKqojUR=aYcraiRC}aefK;!Ri5ra3(7ON$5>zMNg=*~ie V&E4u^J=Weo00%Blg#It(eE}M}B0B&8 literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions1/test.class b/regression/exceptions/exceptions1/test.class new file mode 100644 index 0000000000000000000000000000000000000000..c76687b1bc7a0547086d763afd30f531210e3b7a GIT binary patch literal 1025 zcmZuvZBNr+6g|({ty|ZPF%&@&5kWUp<_m&uXoR7Oro#^y5+Q+fTZQ82Ok0eORw}P5==E;f zRp_%l-(B9@ZMwl*NmeM@-Imi?bplWPlb{}Ldm($+ksC%eR_{8VuP|6zw|AURPNn1c zTa}e4@cgZsbXOdz*-Ok+EkSibO+kx-96<|$I8bvxOO6w4asB`FQ^>7EPU}O%`513Q zai|L=p&AP5`BvwIn7Pv33tH|=PiSOh(`i}GLJ#!;P(Z)J(AoA2e|38i z1l@oXrGbH}g&O7+3TK&bnmcYQqIPGYdWW)8kG30nf!jXq#l@pN{z1*xaGkH#$5&Q` zA(>93fqG+r_XT(nJgW;RQ;<1aL6vgU$mkWZP0kH+T_@fk z*G;nB#Yn8gd-h3VjQ@;Kfdczo#VEHBX|FM^vAe-D&W$GN-5^SGN*)t&MJ-07tZl?- zjA%1P<3!YvRX1sG@eCrpZJ?B2G*FgnO0L^^&cAc|cr$So&|l1bLw+BIegIwj3iJF! RO3Ne?)^mC8yL1wm{teh!r=|b^ literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions1/test.desc b/regression/exceptions/exceptions1/test.desc new file mode 100644 index 00000000000..baf72e7da81 --- /dev/null +++ b/regression/exceptions/exceptions1/test.desc @@ -0,0 +1,10 @@ +CORE +test.class + +^EXIT=10$ +^SIGNAL=0$ +^.*assertion at file test.java line 26 function.*: FAILURE$ +\*\* 1 of 35 failed (2 iterations)$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/exceptions/exceptions1/test.java b/regression/exceptions/exceptions1/test.java new file mode 100644 index 00000000000..bc925b32d65 --- /dev/null +++ b/regression/exceptions/exceptions1/test.java @@ -0,0 +1,30 @@ +class A extends Throwable {} +class B extends A {} +class C extends B {} +class D extends C {} + +public class test { + public static void main (String arg[]) { + try { + D d = new D(); + C c = new C(); + B b = new B(); + A a = new A(); + A e = a; + throw e; + } + catch(D exc) { + assert false; + } + catch(C exc) { + assert false; + } + catch(B exc) { + assert false; + } + catch(A exc) { + assert false; + } + } +} + diff --git a/regression/exceptions/exceptions10/A.class b/regression/exceptions/exceptions10/A.class new file mode 100644 index 0000000000000000000000000000000000000000..963ae156be051ca07ea2d602053e012a3d27a7a4 GIT binary patch literal 241 zcmXX=O;5r=5PbuswY3W2=*gpUuorF+lg8kw;Q*%hZQaP2c5B)#@o#xD@!${OM-gX{ zNoL+h-b?0i{P_hi$0WiKR{^dAj0ygd4ckY;@a{e*cu&o%CX6#SdfnHBZeLVUi8IZb zQdPNX+3BSuQG(CW@UysN#6;bBCelyKv8QYrJ6YoqP1btzNpmRpEZ_t;J0Rp-H$s}9|kN*P*5s4yPo>K82_(?21 literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions10/B.class b/regression/exceptions/exceptions10/B.class new file mode 100644 index 0000000000000000000000000000000000000000..47ae8f218e49b4ac942425d72a88b21c2772b518 GIT binary patch literal 216 zcmXX7D1o9M#q%+AiT z@6YoEV1a=P9X%U;8$Q8WsZ3RCf!TDLcb3PedAtLN)W> zG^(>I`7{ic1ox2FMIv{qi93}ntJy`|ga-pAfda+`BWV1+DPr)3*K{pl# WT<*@-G|^!l`~vXc^F-)=Q^5xrb|NGzlS}mmtic&3AsXFXn91H3~A};DMBd*dk)?i7TBz61){t5m7 zYjj2&nUTFe%JJM-=|UEHxgY1Ad+vSj*Y6)c0j%Mni6R;XZkf=~D4>Ab2AU?aXqa?X z473c~F>x3746G_tmYq2EqQnn__=z7oy`k4vPp=^h)Gu(9|U;J@UPu}@4IqbxXlXY^u4MWoQXxSa{y-%*fR5x+l_b;3e zX%$7Y&4J?w3f1Ntd*Au!w1-YGXm^vy4+iTZLpegRNebPG25eEe0LUQ~@*D1OJb~E_ zN0IA2^F?n#B&`a$g=x%?vSY!*ltOLNvGZ>!PopS|EL={3o9rsp2HFh9BU|a6SQy`qZi{yAdYb>Xb+ut;YQFpJD&;ExO}pLPUgJ5 zs~2-yJ(_tz(#y)+6f;w~rr$ypUfhz_Y;-Nq4`p5DcIuk-B-mxRcs1`PMU34PJ81LZ zNO01?L1Fy!;J)_3E$rkYw{O9f9;f_J@nd1ou&wAPN!VQ>+RSwS8`4)_h(1XpXl6}q ToQk@~D*fN2?r-=3bA-+x##1h8 literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions11/B.class b/regression/exceptions/exceptions11/B.class new file mode 100644 index 0000000000000000000000000000000000000000..3af09687e1afeb9c7dd88272ec5fde0e48c3b12d GIT binary patch literal 216 zcmXX7D18_mM(%+AiT z@6YoEV1a=P9X%U;8$Q8WsZ3RCf!TDLcb3PedAtLN#-1 z8r4~qd>RHzf_up8B9S}Q#GOi()$Af}!h->mKmlWe5j6hZ6fth>=A0{wU*lk3vm!G4I`v^Ugi@-psGxKYjvOz#R)IR1C~o(ByqNi2+3dBm~bpd_V zZ@B`4b+6+-?(Q_);F$yqWb1y@X|FqhC;eVfk6wErIqH!cMvLTl<@@9))yg%pI}Fs9 z85Rv%?z^V+SERqqkBHP-OE2qN&ReJ2b~>BYwJ7j9n~O@H z6Kt|#?mubHMZjEYwtEd(YkoIqx(_`mKPeT?NlF_T46*()zZDy44BEJXQGr6g;PT0^ z9t43O*f@s*rAZ0{H*MU)ZGlW5{-m+xHY4(RoLoP=+UC&NOUn(tz-^t9vg@eJ1Sh_M zaV{*y?TSo6YN4frRa{Ci0>jd`xOcO0|pLZ5MmzbpA=<*L^@)s-~@?5tvc1psij#U z&rE^khIv*|RAMSb*ep6spS{yMudHF(Be^7l6ndy%qXE_#F@k#3zf}` zD4{@^sA=^U{H3&~24?bvUOL^$f+_|KWe2{&-i4v>L63bw{NMeIktYt#z9+X>qNAbw E2bxcsM*si- literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions11/test.desc b/regression/exceptions/exceptions11/test.desc new file mode 100644 index 00000000000..cb92a091217 --- /dev/null +++ b/regression/exceptions/exceptions11/test.desc @@ -0,0 +1,9 @@ +CORE +test.class + +^EXIT=10$ +^SIGNAL=0$ +^.*assertion at file test.java line 36 function.*: FAILURE$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/exceptions/exceptions11/test.java b/regression/exceptions/exceptions11/test.java new file mode 100644 index 00000000000..032af621fc3 --- /dev/null +++ b/regression/exceptions/exceptions11/test.java @@ -0,0 +1,39 @@ +class A extends RuntimeException { + int i=1; +}; + +class B extends A { +}; + +public class test { + static int foo(int k) { + try { + if(k==0) + { + A a = new A(); + throw a; + } + else + { + A b = new A(); + throw b; + } + + } + catch(B exc) { + assert exc.i==1; + } + return 1; + } + + + public static void main (String args[]) { + try { + A a = new A(); + foo(6); + } + catch(A exc) { + assert exc.i==2; + } + } +} diff --git a/regression/exceptions/exceptions12/A.class b/regression/exceptions/exceptions12/A.class new file mode 100644 index 0000000000000000000000000000000000000000..963ae156be051ca07ea2d602053e012a3d27a7a4 GIT binary patch literal 241 zcmXX=O;5r=5PbuswY3W2=*gpUuorF+lg8kw;Q*%hZQaP2c5B)#@o#xD@!${OM-gX{ zNoL+h-b?0i{P_hi$0WiKR{^dAj0ygd4ckY;@a{e*cu&o%CX6#SdfnHBZeLVUi8IZb zQdPNX+3BSuQG(CW@UysN#6;bBCelyKv8QYrJ6YoqP1btzNpmRpEZ_t;J0Rp-H$s}9|kN*P*5s4yPo>K82_(?21 literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions12/B.class b/regression/exceptions/exceptions12/B.class new file mode 100644 index 0000000000000000000000000000000000000000..47ae8f218e49b4ac942425d72a88b21c2772b518 GIT binary patch literal 216 zcmXX7D1o9M#q%+AiT z@6YoEV1a=P9X%U;8$Q8WsZ3RCf!TDLcb3PedAtLN)W> zG^(>I`7{ic1ox2FMIv{qi93}ntJy`|ga-pAfda+`BWV1+DPr)3*K{pl# WT<*@-G|^!l`~vXc^F-)=Q^5xrb|Nukq z=Ym8fD$zS1g?Q_R^nk40ee?8Y-pu&-pP#<~Y~oIc0ILdDLU>pWpm0^;T8OG6yCJUQ zhQdw3(wfe5lNB}{=TB^|hlv>pWM5F*vSV936jatX_5}V;Ix>QVfgPI{lMh3ay>enf zYmmk|+0&VI@s#w7cQ$A0p#OmPn>1z3p^LX&Y(B?=x!pp?@1N_BWePhL)VJbfY8vjQ zlPorU>nwu8{?EwbJZ3YoZDdyMbVysK;0MR_`7| zjtD#~@UESaXc9+LyoeSfU}={8g=&w?$_c#J$6V9B)4@0RhiIIjN}_gpROW`X_Gs)X zxA`xDI=`T7sKNTnY{fZssi{+W0T-FqAlohx9dPD;i7Ex}nL=lt(&bqzo23!3*it`G bKZNqX!moUX|Nl&`MipN4$W6Y&z{BOgR*PqV literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions12/test.class b/regression/exceptions/exceptions12/test.class new file mode 100644 index 0000000000000000000000000000000000000000..a4350fcd81d62534433b034e2f9d88328d74c8b8 GIT binary patch literal 740 zcmZuu%Tg0T6g@q8OfnhrRE($u5H)}j7wn)c1qnOJ^-AHff} zMysGos&wy1S)Lw|EOgP`_ufADoYS{|{`&SEzy=;Ws9?#)T?ZDH%(iUfUKwTFxADM% zZ7#bGR6=*PUJ99BLQ(BP~6g?PM-+mx-0tv`JHH_1ZtiR)vL+z zP{n%&EYS2KUk3X!)+WC!=F_)2A%~Z$B;929vDBf!Z1;_KBtOVrAj5HQkj6S3ZyI)S zNFA?FWKMnbO}uToWIQHI>px8bGlNw6?_SFHnIs=6P}=f?OViFEn#8{9Yh$r&T&x>m z7gf|K*LU$S3$|Ujm=S1CZ9V%tkQZ?r#dKl1Z9HuSq<}#KJ5x3cUhs%bwYh%7jXy@ud8yO5} fG|OjjPGHkeKKB*He;;Q!3b5R#W&{gNEG+&8z8Qep literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions12/test.desc b/regression/exceptions/exceptions12/test.desc new file mode 100644 index 00000000000..4654e88cbb6 --- /dev/null +++ b/regression/exceptions/exceptions12/test.desc @@ -0,0 +1,9 @@ +CORE +test.class + +^EXIT=10$ +^SIGNAL=0$ +^.*assertion at file test.java line 12 function.*: FAILURE$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/exceptions/exceptions12/test.java b/regression/exceptions/exceptions12/test.java new file mode 100644 index 00000000000..5828419fac6 --- /dev/null +++ b/regression/exceptions/exceptions12/test.java @@ -0,0 +1,27 @@ +class A extends RuntimeException {} +class B extends A {} +class C extends B {} + +class F { + void foo() { + try { + B b = new B(); + throw b; + } + catch(B exc) { + assert false; + } + } +} + +public class test { + public static void main (String args[]) { + try { + F f = new F(); + f.foo(); + } + catch(B exc) { + assert false; + } + } +} diff --git a/regression/exceptions/exceptions13/A.class b/regression/exceptions/exceptions13/A.class new file mode 100644 index 0000000000000000000000000000000000000000..963ae156be051ca07ea2d602053e012a3d27a7a4 GIT binary patch literal 241 zcmXX=O;5r=5PbuswY3W2=*gpUuorF+lg8kw;Q*%hZQaP2c5B)#@o#xD@!${OM-gX{ zNoL+h-b?0i{P_hi$0WiKR{^dAj0ygd4ckY;@a{e*cu&o%CX6#SdfnHBZeLVUi8IZb zQdPNX+3BSuQG(CW@UysN#6;bBCelyKv8QYrJ6YoqP1btzNpmRpEZ_t;J0Rp-H$s}9|kN*P*5s4yPo>K82_(?21 literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions13/B.class b/regression/exceptions/exceptions13/B.class new file mode 100644 index 0000000000000000000000000000000000000000..47ae8f218e49b4ac942425d72a88b21c2772b518 GIT binary patch literal 216 zcmXX7D1o9M#q%+AiT z@6YoEV1a=P9X%U;8$Q8WsZ3RCf!TDLcb3PedAtLN)W> zG^(>I`7{ic1ox2FMIv{qi93}ntJy`|ga-pAfda+`BWV1+DPr)3*K{pl# WT<*@-G|^!l`~vXc^F-)=Q^5xrb|N~W_5d{6*B%>=cEi9Za@cY?f zme?@W+*)qu`SH-amqnOJ^-AHff} zMysGos&wy1S)Lw|EOgP`_ufADoYS{|{`&SEzy=;Ws9?#)T?ZDH%(iUfUKwTFxADM% zZ7#bGR6=*PUJ99BLQ(BP~6g?PM-+mx-0tv`JHH_1ZtiR)vL+z zP{n%&EYS2KUk3X!)+WC!=F_)2A%~Z$B;929vDBf!Z1;_KBtOVrAj5HQkj6S3ZyI)S zNFA?FWKMnbO}uToWIQHI>px8bGlNw6?_SFHnIs=6P}=f?OViFEn#8{9Yh$r&T&x>m z7gf|K*LU$S3$|Ujm=S1CZ9V%tkQZ?r#dKl1Z9HuSq<}#KJ5x3cUhs%bwYh%7jXy@ud8yO5} fG|OjjPGHkeKKB*He;;Q!3b5R#W&{gNEG+&8z8Qep literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions13/test.desc b/regression/exceptions/exceptions13/test.desc new file mode 100644 index 00000000000..cb7c1b81341 --- /dev/null +++ b/regression/exceptions/exceptions13/test.desc @@ -0,0 +1,9 @@ +CORE +test.class + +^EXIT=10$ +^SIGNAL=0$ +^.*assertion at file test.java line 25 function.*: FAILURE$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/exceptions/exceptions13/test.java b/regression/exceptions/exceptions13/test.java new file mode 100644 index 00000000000..56d763f68d3 --- /dev/null +++ b/regression/exceptions/exceptions13/test.java @@ -0,0 +1,28 @@ +class A extends RuntimeException {} +class B extends A {} +class C extends B {} + +class F { + void foo() { + try { + B b = new B(); + throw b; + } + catch(B exc) { + throw exc; + } + } +} + +public class test { + + public static void main (String args[]) { + try { + F f = new F(); + f.foo(); + } + catch(B exc) { + assert false; + } + } +} diff --git a/regression/exceptions/exceptions14/A.class b/regression/exceptions/exceptions14/A.class new file mode 100644 index 0000000000000000000000000000000000000000..963ae156be051ca07ea2d602053e012a3d27a7a4 GIT binary patch literal 241 zcmXX=O;5r=5PbuswY3W2=*gpUuorF+lg8kw;Q*%hZQaP2c5B)#@o#xD@!${OM-gX{ zNoL+h-b?0i{P_hi$0WiKR{^dAj0ygd4ckY;@a{e*cu&o%CX6#SdfnHBZeLVUi8IZb zQdPNX+3BSuQG(CW@UysN#6;bBCelyKv8QYrJ6YoqP1btzNpmRpEZ_t;J0Rp-H$s}9|kN*P*5s4yPo>K82_(?21 literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions14/B.class b/regression/exceptions/exceptions14/B.class new file mode 100644 index 0000000000000000000000000000000000000000..47ae8f218e49b4ac942425d72a88b21c2772b518 GIT binary patch literal 216 zcmXX7D1o9M#q%+AiT z@6YoEV1a=P9X%U;8$Q8WsZ3RCf!TDLcb3PedAtLN)W> zG^(>I`7{ic1ox2FMIv{qi93}ntJy`|ga-pAfda+`BWV1+DPr)3*K{pl# WT<*@-G|^!l`~vXc^F-)=Q^5xrb|NKQjnAn#E;R9?=Y8JyydTf=o__!NT6@^@1Qu*R z@ScxOx?cEFCJW^4q3a9|ozR#5G^oXI{D?j5*o)$AR-ZV2Ah1+>Z67=Do%+BD`t?p6 z`ayqNb{8(^*llL2-iHLYB(|Hf)(QLURrp7#zCjx5%nH_g96<~CR zqtNyCd`UMe8LdkaCKh0Ebemt(#5{5Wr5U^CpS|pc;V@)Qi&SK>j)x{5VMD;0Wxwbi zdv47A%tGw}S4+)3FY-gLchQfG;}I{o*CQ| zcl=-EENNzOsKTZeDjX(%yG{OOYC>xx(UL`msw`3{&@WQg3UP(1s*E;BbCWk)yxAjF zDWQQBYceR|3aJ;lhpP#yCg>VtTM4?JNZrQ`++@`)ev3$VbllFhbS%qbCC4^*F4osb h3YeBRK4b0_x;BQUenR^1RmyHDDCSeS@G>0*m0$24k%|BS literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions14/test.desc b/regression/exceptions/exceptions14/test.desc new file mode 100644 index 00000000000..dc5ca4fa5cb --- /dev/null +++ b/regression/exceptions/exceptions14/test.desc @@ -0,0 +1,8 @@ +CORE +test.class + +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/exceptions/exceptions14/test.java b/regression/exceptions/exceptions14/test.java new file mode 100644 index 00000000000..24f44a5d3d9 --- /dev/null +++ b/regression/exceptions/exceptions14/test.java @@ -0,0 +1,24 @@ +class A extends RuntimeException {} +class B extends A {} +class C extends B {} + +public class test { + public static void main (String args[]) { + try { + try { + C c = new C(); + A a = new A(); + } + catch(C exc) { + assert false; + } + catch(B exc) { + assert false; + } + } + catch(A exc) { + assert false; + } + + } +} diff --git a/regression/exceptions/exceptions2/A.class b/regression/exceptions/exceptions2/A.class new file mode 100644 index 0000000000000000000000000000000000000000..eb19ef6be2b4b0dc315cdfd2ae091ecc67882efd GIT binary patch literal 234 zcmXX=%MQU%5IsX5TBX7dSYn|YJ0fW$R*em@zv_l7)h5;QT~-ncAK;_J+%n0`dF0Gw z-k;|Szyuu^b+l}>ZTJLhrczbR3H8BnOE4DMUK0FBrE*oCcQW6IUBXT`%3_ghMXt2| zn?`X|7ha9RDZyQ5Wgg3=(s8GdmtuSpSK+~cNuZF>(>h2*dI&bhJiF;j=%dE}=pt^; iGFr?6M(voR2k6eE2Aii7D1o9M#q%+AiT z@6YoEV1a=P9X%U;8$Q8WsZ3RCf!TDLcb3PedAtLN)W> zG^(>I`7{ic1ox2FMIv{qi93}ntJy`|ga-pAfda+`BWV1+DPr)3*K{pl# WT<*@-G|^!l`~vXc^F-)=Q^5xrb|Nfgc6r6RO*m2x6O`rrwftCVkQkqL|tq>%@0U0<1Rid0W&MIti9b`L*-_k$O zbBjbJD$zSX3Naf(BLs)_``9;c=DqcgpWnU%*v6Iz4{HwYda#ULFT%w=2lqV`O#Hw@ z6B`a%0=0FSrYgzwI8LAHR1P9F6cGCYg=9%t&31@BlsXnzZoUf+3-?PC)U1uFB(*MkEUW?acU)r+`IjyY7RPSo(S z7o}zsUT~HBSmk4Qd?!(<8+Lj*a2%BRU1Zdu6}0)*8N>-43l)9~zmr&^@6Y@yYK)4w zf~(9J@F}Y;+RbxVZ_l{L_C;`t{1Hm$C@|q%9P`Eg&YVmU=AW^N^w40On{uvEDtKIS zcob{oUgu4NVpqu5rW&KCMWjpAGOkfaiMMsu3Dy|Tn|0k`U}5za)c=H& literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions2/test.desc b/regression/exceptions/exceptions2/test.desc new file mode 100644 index 00000000000..eb7fa309bea --- /dev/null +++ b/regression/exceptions/exceptions2/test.desc @@ -0,0 +1,10 @@ +CORE +test.class + +^EXIT=10$ +^SIGNAL=0$ +^.*assertion at file test.java line 15 function.*: FAILURE$ +^\*\* 1 of 20 failed (2 iterations)$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/exceptions/exceptions2/test.java b/regression/exceptions/exceptions2/test.java new file mode 100644 index 00000000000..420b50219c1 --- /dev/null +++ b/regression/exceptions/exceptions2/test.java @@ -0,0 +1,18 @@ +class A extends Throwable {} +class B extends A {} +class C extends B {} + +public class test { + public static void main (String args[]) { + try { + B b = new B(); + throw b; + } + catch(C exc) { + assert false; + } + catch(B exc) { + assert false; + } + } +} diff --git a/regression/exceptions/exceptions3/A.class b/regression/exceptions/exceptions3/A.class new file mode 100644 index 0000000000000000000000000000000000000000..eb19ef6be2b4b0dc315cdfd2ae091ecc67882efd GIT binary patch literal 234 zcmXX=%MQU%5IsX5TBX7dSYn|YJ0fW$R*em@zv_l7)h5;QT~-ncAK;_J+%n0`dF0Gw z-k;|Szyuu^b+l}>ZTJLhrczbR3H8BnOE4DMUK0FBrE*oCcQW6IUBXT`%3_ghMXt2| zn?`X|7ha9RDZyQ5Wgg3=(s8GdmtuSpSK+~cNuZF>(>h2*dI&bhJiF;j=%dE}=pt^; iGFr?6M(voR2k6eE2Aii7D1o9M#q%+AiT z@6YoEV1a=P9X%U;8$Q8WsZ3RCf!TDLcb3PedAtLN)W> zG^(>I`7{ic1ox2FMIv{qi93}ntJy`|ga-pAfda+`BWV1+DPr)3*K{pl# WT<*@-G|^!l`~vXc^F-)=Q^5xrb|Nfgc5PfSqaqPNjnm`BzN(%*&@R3Vztq>%DI2d{eszf<$oK@J8I>>eqzokbm zJr^V@QHkF9QHZxDG(vFLoq4lwX5P&H`1$QSfKA-@;bYy!4Ih@VH$9ZF;o_E$qQSR) z+(FYtOQ5zP(^Msyp2X=Boyx&j4F$xWKyh2gI(sN!H(R>`PH!?)0!yKe)ywI@KqapX zS)dwDB01ibi8go^bh5WPWsNXXX|~1e1F2(ydh<=VFF(l6SjMAHKTC8x+A`H`^)ccd z_QO!6dq92e^xS0+l&)XRxoLjO&<(dSh;qBMw!n6E!@q zMXA}84_xCO*7*@W|439CraL_w90z6IOGF)7L0f2_KpfMtP~lzt9mF#IVCGj*Bl2(o z7a1|hpUAdo+o!NzpTIr~KcjGng;Nv>-LoV9)!&ihoL{0Shj}He5ZigjRk(S?$n_}o z5<9F==oLzBkztgqk?RrH`6}|4IvTmUHZGG5#*AL)xr?jiu8V7B_EZTJLhrczbR3H8BnOE4DMUK0FBrE*oCcQW6IUBXT`%3_ghMXt2| zn?`X|7ha9RDZyQ5Wgg3=(s8GdmtuSpSK+~cNuZF>(>h2*dI&bhJiF;j=%dE}=pt^; iGFr?6M(voR2k6eE2Aii7D1o9M#q%+AiT z@6YoEV1a=P9X%U;8$Q8WsZ3RCf!TDLcb3PedAtLN)W> zG^(>I`7{ic1ox2FMIv{qi93}ntJy`|ga-pAfda+`BWV1+DPr)3*K{pl# WT<*@-G|^!l`~vXc^F-)=Q^5xrb|Nfgc5Pj=7apJgXnm|b*4gCVr7Me?Mtq>%@0U3G-szf<$oK@J8+Q@bgzl1~o z0Ox{4B`VQ7KML{IgysOUc6Vm>&Ad0W{`u?s4*Y0ysJ>V!4?R3+&ivrnWB1s2!u>G?PWBwAGSQkzDxs0U+hmj(` z6657e;1Vl0DQ}qw!@fdnkr|7)LDn*F8d%B{wQv)+h-h+ou%A0vu5=x=OvT$*4en-G gV4+t0hSDhZTJLhrczbR3H8BnOE4DMUK0FBrE*oCcQW6IUBXT`%3_ghMXt2| zn?`X|7ha9RDZyQ5Wgg3=(s8GdmtuSpSK+~cNuZF>(>h2*dI&bhJiF;j=%dE}=pt^; iGFr?6M(voR2k6eE2Aii7D1o9M#q%+AiT z@6YoEV1a=P9X%U;8$Q8WsZ3RCf!TDLcb3PedAtLN)W> zG^(>I`7{ic1ox2FMIv{qi93}ntJy`|ga-pAfda+`BWV1+DPr)3*K{pl# WT<*@-G|^!l`~vXc^F-)=Q^5xrb|N0ia<-WNlvOJ0;V`m%{smNkcs&?*7 zqdu#OPor>6a1TXOrgEp+xKqojUR=aYcraiRC}aefK;!Ri5ra3(7ON$5>zMNg=*~ie V&E4u^J=Weo00%Blg#It(eE}M}B0B&8 literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions5/test.class b/regression/exceptions/exceptions5/test.class new file mode 100644 index 0000000000000000000000000000000000000000..1b251e32471f5d7fe325eac698256834648f5e0a GIT binary patch literal 997 zcmZuv+fEZv6kVq??X=U<7SKw)AS&p9O1)Ik77etO#AJ#O7!tuC({=)br8P5y@mu%- zp3y`So5;H#Wn6nic)&F0?6r6IZLKrEe*gFhpo|wLawr*iU?L{=p$T2=BNGX+k4+>| zN?{0P15Zq(CHU0D9G)3?t}r_31cB>^UcVPKyufL7-Hw73oW| zp*Ylql28qWqNx%U}ef9M#~d^VE12Gst6DVeD-C#ecfJ z^8LO~iqgP9C4(yF74m19Z(2KUJEV4Jp?a6HQ;&`tc)r^??Zw5zJ^n$>*KmWcmg6g{ z{FqE9(m=g2%KHMn60M?*&m2J=62x$kcOnYvC=h4tZhbUBGPe_ zxwqN<4o?BeZ39-eW?)*b8M*F)Q}3NVP&ujshDV0JBfAenKY*@%gL(e3q-7kj%z`}W JeL6AB{sHnbp}znC literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions5/test.desc b/regression/exceptions/exceptions5/test.desc new file mode 100644 index 00000000000..dc5ca4fa5cb --- /dev/null +++ b/regression/exceptions/exceptions5/test.desc @@ -0,0 +1,8 @@ +CORE +test.class + +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/exceptions/exceptions5/test.java b/regression/exceptions/exceptions5/test.java new file mode 100644 index 00000000000..e539f06df1e --- /dev/null +++ b/regression/exceptions/exceptions5/test.java @@ -0,0 +1,27 @@ +class A extends Throwable {} +class B extends A {} +class C extends B {} +class D extends C {}public class test { + public static void main (String arg[]) { + try { + D d = new D(); + C c = new C(); + B b = new B(); + A a = new A(); + A e = a; + throw e; + } + catch(D exc) { + assert false; + } + catch(C exc) { + assert false; + } + catch(B exc) { + assert false; + } + catch(A exc) { + } + } +} + diff --git a/regression/exceptions/exceptions6/A.class b/regression/exceptions/exceptions6/A.class new file mode 100644 index 0000000000000000000000000000000000000000..fbaaf105dbaddd4eb32dc843a524880a3ff50fe4 GIT binary patch literal 280 zcmXYru};H45JYF4ON@<4AW%_JLJHE*5g|ngBqWOhQ2L8G!6N63oHNRAQ6MA=K7fxx zj6;gO-FZ8s+n?XBZvbaFNMW#>po6^_!x;MlQPz#1H&L(QLeM!rnF-8g_2>kHT)n$( z7IRlW*m+4Z%&WqdGh1t`H_(J7D1o9M#q%+AiT z@6YoEV1a=P9X%U;8$Q8WsZ3RCf!TDLcb3PedAtLN)W> zG^(>I`7{ic1ox2FMIv{qi93}ntJy`|ga-pAfda+`BWV1+DPr)3*?v$M18 z`}2GOSYqfwN8iT4MnJIEDp&P}piibT!3c|!Bm|Ml<-WNlvOJ0;V`mf*X@L|9tP{`O~42{3HMGW3BTdWq$tz*s}pgRi< WHg~Ht9XPE0UjQyVo(R1z<$nPh2O>NG literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions6/D.class b/regression/exceptions/exceptions6/D.class new file mode 100644 index 0000000000000000000000000000000000000000..12179e84294d669f8f9f06e51f5400f5cc8f5db6 GIT binary patch literal 216 zcmXX0ia<-WNlvOJ0;V`m%{smNkcs&?*7 zqdu#OPor>6a1TXOrgEp+xKqojUR=aYcraiRC}aefK;!Ri5ra3(7ON$5>zMNg=*~ie V&E4u^J=Weo00%Blg#It(eE}M}B0B&8 literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions6/test.class b/regression/exceptions/exceptions6/test.class new file mode 100644 index 0000000000000000000000000000000000000000..e0c57f3e31882cdf481a96c6f9f53834e3440c85 GIT binary patch literal 806 zcmZuv&2JJx9DTF9u95vnGdRS%dZ*3+_Va4KEQ?qd8~dhytE z)!4))Hu2~mWqh;NVxotc`F+0Mn>X|0=htrlHgMO5gNBLgHZ(LW*tlWQYMNNJkyV+N zg`D!&Y}~{x6YBz{x);Yml*nlqKajCEoCG5Qu`Q78%1|cv1oYvhMR)3ZlPxcj%0CGj$!i%C!%c!X>9Bj(lc7Ml`O4k#-g)hb7mnM5B$DB{ zqtJ!qddykDd!M`8V~_6kRi_t?iB$Seqrk!-@%%SWy|?LDUY&Oo$aVe633q!iokf1| zNGhh5BD1dMJ6J@46MGI8aK=Fe%L0`-v)&&~9!AkLVqu>|RJVz?gWI?xP?%RgAMONx zLT%=u%?V}YeMdnoqhNH3N509732M5H8lTAF(}_Yw(V(S+C@64WqSxjrcxGCM5C=3g z6uD>9pp6o3=XU|l;v78-Wt?Y3HGgNd#^gZg$fASglwS)5YjR3p^2#$) z#RXcbrizOx`z|iwGSRMZIWV4>xLWR;sFm5baw^6~S_>={?Jvmh!8G<^=$~NxD~tll OKy&UZ`L5B?Q2zx(l8Oxg literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions6/test.desc b/regression/exceptions/exceptions6/test.desc new file mode 100644 index 00000000000..79549d80731 --- /dev/null +++ b/regression/exceptions/exceptions6/test.desc @@ -0,0 +1,9 @@ +CORE +test.class + +^EXIT=10$ +^SIGNAL=0$ +^.*assertion at file test.java line 18 function.*: FAILURE$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/exceptions/exceptions6/test.java b/regression/exceptions/exceptions6/test.java new file mode 100644 index 00000000000..fd9a7fd5326 --- /dev/null +++ b/regression/exceptions/exceptions6/test.java @@ -0,0 +1,26 @@ +class A extends RuntimeException { + int i; + A() { + i = 1; + } +} +class B extends A {} +class C extends B {} + +public class test { + public static void main (String args[]) { + try { + try { + int i = 0; + throw new A(); + } + catch(A exc) { + assert exc.i==2; + } + } + catch(B exc) { + assert exc.i==2; + } + + } +} diff --git a/regression/exceptions/exceptions7/A.class b/regression/exceptions/exceptions7/A.class new file mode 100644 index 0000000000000000000000000000000000000000..963ae156be051ca07ea2d602053e012a3d27a7a4 GIT binary patch literal 241 zcmXX=O;5r=5PbuswY3W2=*gpUuorF+lg8kw;Q*%hZQaP2c5B)#@o#xD@!${OM-gX{ zNoL+h-b?0i{P_hi$0WiKR{^dAj0ygd4ckY;@a{e*cu&o%CX6#SdfnHBZeLVUi8IZb zQdPNX+3BSuQG(CW@UysN#6;bBCelyKv8QYrJ6YoqP1btzNpmRpEZ_t;J0Rp-H$s}9|kN*P*5s4yPo>K82_(?21 literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions7/B.class b/regression/exceptions/exceptions7/B.class new file mode 100644 index 0000000000000000000000000000000000000000..47ae8f218e49b4ac942425d72a88b21c2772b518 GIT binary patch literal 216 zcmXX7D1o9M#q%+AiT z@6YoEV1a=P9X%U;8$Q8WsZ3RCf!TDLcb3PedAtLN)W> zG^(>I`7{ic1ox2FMIv{qi93}ntJy`|ga-pAfda+`BWV1+DPr)3*K{pl# WT<*@-G|^!l`~vXc^F-)=Q^5xrb|NB-u+J+&n?qEXyU`Y_q(UxcfNDJ+wVWWegjZL&47s&9jgWud6o@mSV_acnvRDC zbP2BOcw}G$6&;TS3d>Fyx|^JHQyDmZztWBZ z&+qR@cF|=YyU9%9$f(Xpbw9>vL)JS%pL~UXlnZ3rk<)#5;JlBU(|&BSERfpm4kjjy z_HYz*-IgaMr=_Y5Da6DKEH-U&)lFoP6DUp<)_>1tKL~~aa~hN)i*-CPv5BgHHO+p} zId;1dXEcSH1CE!zdv53jZto8t6-Og};B1eu#0N6@fWj(D1&maX1s3;N-YPr=&&1jV z#5n^6dG5(85Cz8OB%Z@H-qM)Ibt1C(2eVb4tud6>7aZ*v8qdVR`lbB|$x~#;&3ni+mQr{NluuZl5 zD8>%<=ttHRaf8Y&^54V)cUgNY#!7K?n_su%Xd(98!W}G9!(FafBwy-S$~AP{liU3q oDP_~EQPkoBrsa(<$ecpg&Y-EEk^Fn6k}Uznd@3hj;zhxOUndZfg#Z8m literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions7/test.desc b/regression/exceptions/exceptions7/test.desc new file mode 100644 index 00000000000..e138e4349ec --- /dev/null +++ b/regression/exceptions/exceptions7/test.desc @@ -0,0 +1,9 @@ +CORE +test.class + +^EXIT=10$ +^SIGNAL=0$ +^.*assertion at file test.java line 21 function.*: FAILURE$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/exceptions/exceptions7/test.java b/regression/exceptions/exceptions7/test.java new file mode 100644 index 00000000000..e03be8a56fb --- /dev/null +++ b/regression/exceptions/exceptions7/test.java @@ -0,0 +1,25 @@ +class A extends RuntimeException {} +class B extends A {} +class C extends B {} + +public class test { + public static void main (String args[]) { + try { + try { + C c = new C(); + A a = new A(); + throw a; + } + catch(C exc) { + assert false; + } + catch(B exc) { + assert false; + } + } + catch(A exc) { + assert false; + } + + } +} diff --git a/regression/exceptions/exceptions8/A.class b/regression/exceptions/exceptions8/A.class new file mode 100644 index 0000000000000000000000000000000000000000..963ae156be051ca07ea2d602053e012a3d27a7a4 GIT binary patch literal 241 zcmXX=O;5r=5PbuswY3W2=*gpUuorF+lg8kw;Q*%hZQaP2c5B)#@o#xD@!${OM-gX{ zNoL+h-b?0i{P_hi$0WiKR{^dAj0ygd4ckY;@a{e*cu&o%CX6#SdfnHBZeLVUi8IZb zQdPNX+3BSuQG(CW@UysN#6;bBCelyKv8QYrJ6YoqP1btzNpmRpEZ_t;J0Rp-H$s}9|kN*P*5s4yPo>K82_(?21 literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions8/B.class b/regression/exceptions/exceptions8/B.class new file mode 100644 index 0000000000000000000000000000000000000000..47ae8f218e49b4ac942425d72a88b21c2772b518 GIT binary patch literal 216 zcmXX7D1o9M#q%+AiT z@6YoEV1a=P9X%U;8$Q8WsZ3RCf!TDLcb3PedAtLN)W> zG^(>I`7{ic1ox2FMIv{qi93}ntJy`|ga-pAfda+`BWV1+DPr)3*K{pl# WT<*@-G|^!l`~vXc^F-)=Q^5xrb|Nfgc5Ph3Cwd2@nJ|MJEXn<0Z6dFDX92y~#00-*AA*d4NQYh~Lsb z&~rheKqPwSMRbKYo7u4qycjOxUREsF_H}xuoNUi4>|PGPs%M zwydLWA}yDKU-GSFvP@4)<4S(pz4;7M?>V|^W4*H(L zwBrxG=X<+dFMKJ%3I!+Vxq}Ti^u?YywfK!6k;93-C|)JURuGW3OXRe~_CE9kw~6ge z?DpQSyYI%il+I$iu0K>LRbD$g?t8aBaEIIVP8|Bf?Nt$@TuE*+S#!f}7ApQHki*~* z6pTi1Floi?1bbo6d+Lkuv}juvehWF|$=c#-b2TlTL*7Cb(+V@E3YvdL^&|{~ki~^T z$BKn}xUY~qjeODF@p>`Gb?RylIBE9O_aZ;^`X^lMKHlR6$GnNld?=d_s&X?@ok#_5ZRp+UArfNq}hXe@}xljFe;ta7h!DmsTWk@IVNb(k=6FjpcBwigMxmG(~OEwP2 z@g_``N{-n|{5O(m@VChK$&k~g9APh!!Qh&~EUgUDd0ZfxlWdliWSexUiMU15gY6iUnxQ0{lCo@a zjxy#cs!T!4v_x!;Eg8%#bFPX}S>DYOmB&bYGSMrz%2OJ!psnjz$hLG`%QAEEWOOUz iSRh}>e1^3TT|0o5`~>6QHxQx}64oPmsp~WnsQdzqm68qs literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions8/test.desc b/regression/exceptions/exceptions8/test.desc new file mode 100644 index 00000000000..a400cbb8d02 --- /dev/null +++ b/regression/exceptions/exceptions8/test.desc @@ -0,0 +1,9 @@ +CORE +test.class + +^EXIT=10$ +^SIGNAL=0$ +^.*assertion at file test.java line 23 function.*: FAILURE$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/exceptions/exceptions8/test.java b/regression/exceptions/exceptions8/test.java new file mode 100644 index 00000000000..7d6af5324b7 --- /dev/null +++ b/regression/exceptions/exceptions8/test.java @@ -0,0 +1,29 @@ +class A extends RuntimeException {} +class B extends A {} +class C extends B {} + +public class test { + static void foo() { + try { + B b = new B(); + throw b; + } + catch(C exc) { + int i=0; + } + } + + public static void main (String args[]) { + try { + A a = new A(); + foo(); + throw a; + } + catch(B exc) { + assert false; + } + catch(A exc) { + assert false; + } + } +} diff --git a/regression/exceptions/exceptions9/A.class b/regression/exceptions/exceptions9/A.class new file mode 100644 index 0000000000000000000000000000000000000000..ad46eafd1d9234e74590cd579aff0f7eb17f9bfd GIT binary patch literal 276 zcmXYrK}*9x5QX2QYh%`EYxU&GqxN7g9t4X}N((~ppwjy`F1nI#B;AOA%Yz6W`UCt? z#h2Q{%$xaU9y7n|pA~>h9BU|a6SQy`qZi{yAdYb>Xb+ut;YQFpJD&;ExO}pLPUgJ5 zs~2-yJ(_tz(#y)+6f;w~rr$ypUfhz_Y;-Nq4`p5DcIuk-B-mxRcs1`PMU34PJ81LZ zNO01?L1Fy!;J)_3E$rkYw{O9f9;f_J@nd1ou&wAPN!VQ>+RSwS8`4)_h(1XpXl6}q ToQk@~D*fN2?r-=3bA-+x##1h8 literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions9/B.class b/regression/exceptions/exceptions9/B.class new file mode 100644 index 0000000000000000000000000000000000000000..3af09687e1afeb9c7dd88272ec5fde0e48c3b12d GIT binary patch literal 216 zcmXX7D18_mM(%+AiT z@6YoEV1a=P9X%U;8$Q8WsZ3RCf!TDLcb3PedAtLN#-1 z8r4~qd>RHzf_up8B9S}Q#GOi()$Af}!h->mKmlWe5j6hZ6ftK{pl# WT<*@-G|^!l`~vXc^F-)=Q^5xrb|Nl=Sil_%DO3#1TF~TuIf(&WNkYe* zfvN=q6^oIpNv0W@w{Q*D4J-)cCY>;JgUIu{;e9W38XdPKAT|UNOJ3KD?h3?8<#hpl z)o-~1gLSX#KHk}GxWO|C7Rc89rqfw>0#EwApdP*ULUPn2H;fj^@yhqfQL2?|WOo>- zFEcC}wA^=1>90tCiyslGwa961J#yYCI`+f2+m6>2$d_K$H=Vamwc~W#)wL+_y6r`! z&k5SBnEOwfa}h9?nw?%l)|$T)G~I`ul%JFe=Om?#42D>Lncs?yGzM+lz^Fi>UvT+k zSPz204{V%6fzl*}ftxmN;kH1g4}a3wbej?RJWj43UhQz`?4{*~Uf{M)N!fL@!vrV3 zfpIP@#qEkrL299;gX9?EnWb0dEqKQ(2N3%-G~{?DRM5m3+V(L3XOX98O0|s0#~+E- zc+VGikvfF-;(!~NJ?dNa&xr3LH~SR{{R0LLVGv>->7Nv3fkZlDs^A2PL9IH~%BiJU zAkR#J<%W4yQB-0oMA$4kOrO2eI|^7$T$eZ|(_iuV<9nq$*?f{UDyEMaoQX-qRSN$M$-Fr$Qy5oZ!}EL1i# zqJ#ovBB#__@R!n_8ko)#I&->{1yu|f$_{*ky$eI%gC6^W_`mxZBTpQfeNS$&L`OsU E51X%=N&o-= literal 0 HcmV?d00001 diff --git a/regression/exceptions/exceptions9/test.desc b/regression/exceptions/exceptions9/test.desc new file mode 100644 index 00000000000..dc5ca4fa5cb --- /dev/null +++ b/regression/exceptions/exceptions9/test.desc @@ -0,0 +1,8 @@ +CORE +test.class + +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/exceptions/exceptions9/test.java b/regression/exceptions/exceptions9/test.java new file mode 100644 index 00000000000..53f7838fd03 --- /dev/null +++ b/regression/exceptions/exceptions9/test.java @@ -0,0 +1,39 @@ +class A extends RuntimeException { + int i=1; +}; + +class B extends A { +}; + +public class test { + static int foo(int k) { + try { + if(k==0) + { + A a = new A(); + throw a; + } + else + { + A b = new A(); + throw b; + } + + } + catch(B exc) { + assert exc.i==1; + } + return 1; + } + + + public static void main (String args[]) { + try { + A a = new A(); + foo(6); + } + catch(A exc) { + assert exc.i==1; + } + } +} From a07691896f8640a0b12cf24c75157720ab0d7d4f Mon Sep 17 00:00:00 2001 From: Cristina Date: Wed, 8 Feb 2017 17:26:27 +0000 Subject: [PATCH 103/699] Recreate the try-catch structure from the exception table - Adjust the working set conversion algorithm from bytecode to codet to also handler exception handlers. - Use CATCH-PUSH and CATCH-POP expressions to recreate the try-catch blocks. --- .../java_bytecode_convert_method.cpp | 225 ++++++++++++++++-- .../java_bytecode_convert_method_class.h | 1 + 2 files changed, 201 insertions(+), 25 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 3ce43acff02..6f816424354 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -157,6 +157,13 @@ exprt::operandst java_bytecode_convert_methodt::pop(std::size_t n) return operands; } +void java_bytecode_convert_methodt::pop_residue(std::size_t n) +{ + std::size_t residue_size=n<=stack.size()?n:stack.size(); + + stack.resize(stack.size()-residue_size); +} + void java_bytecode_convert_methodt::push(const exprt::operandst &o) { stack.resize(stack.size()+o.size()); @@ -218,7 +225,6 @@ const exprt java_bytecode_convert_methodt::variable( symbol_exprt result(identifier, t); result.set(ID_C_base_name, base_name); used_local_names.insert(result); - return result; } else @@ -952,6 +958,24 @@ codet java_bytecode_convert_methodt::convert_instructions( a_entry.first->second.successors.push_back(next->address); } + if(i_it->statement=="athrow" || + i_it->statement=="invokestatic" || + i_it->statement=="invokevirtual") + { + // find the corresponding try-catch blocks and add the handlers + // to the targets + for(std::size_t e=0; eaddress>=method.exception_table[e].start_pc && + i_it->addresssecond.successors.push_back( + method.exception_table[e].handler_pc); + targets.insert(method.exception_table[e].handler_pc); + } + } + } + if(i_it->statement=="goto" || i_it->statement==patternt("if_?cmp??") || i_it->statement==patternt("if??") || @@ -1029,7 +1053,6 @@ codet java_bytecode_convert_methodt::convert_instructions( setup_local_variables(method, address_map); std::set working_set; - bool assertion_failure=false; if(!instructions.empty()) working_set.insert(instructions.front().address); @@ -1039,6 +1062,7 @@ codet java_bytecode_convert_methodt::convert_instructions( std::set::iterator cur=working_set.begin(); address_mapt::iterator a_it=address_map.find(*cur); assert(a_it!=address_map.end()); + unsigned cur_pc=*cur; working_set.erase(cur); if(a_it->second.done) @@ -1075,6 +1099,46 @@ codet java_bytecode_convert_methodt::convert_instructions( statement=std::string(id2string(statement), 0, statement.size()-2); } + // we throw away the first statement in an exception handler + // as we don't know if a function call had a normal or exceptional return + size_t e; + for(e=0; eaddress, + false); + + // throw away the operands + pop_residue(bytecode_info.pop); + + // add a CATCH-PUSH signaling a handler + side_effect_expr_catcht catch_handler_expr; + // pack the exception variable so that it can be used + // later for instrumentation + catch_handler_expr.set(ID_handler, exc_var); + codet catch_handler=code_expressiont(catch_handler_expr); + + code_labelt newlabel(label(i2string(cur_pc)), code_blockt()); + code_blockt label_block=to_code_block(newlabel.code()); + code_blockt handler_block; + handler_block.move_to_operands(c); + handler_block.move_to_operands(catch_handler); + handler_block.move_to_operands(label_block); + c=handler_block; + + break; + } + } + + if(esource_location; - throw_expr.copy_to_operands(op[0]); - c=code_expressiont(throw_expr); - results[0]=op[0]; - } - else - { - // TODO: this can be removed once we properly handle throw - // if this athrow is generated by an assertion, then skip it - c=code_skipt(); - assertion_failure=false; - } + side_effect_expr_throwt throw_expr; + throw_expr.add_source_location()=i_it->source_location; + throw_expr.copy_to_operands(op[0]); + c=code_expressiont(throw_expr); + results[0]=op[0]; } else if(statement=="checkcast") { @@ -1167,14 +1221,7 @@ codet java_bytecode_convert_methodt::convert_instructions( statement=="invokevirtual" || statement=="invokestatic") { - // Remember that this is triggered by an assertion - if(statement=="invokespecial" && - id2string(arg0.get(ID_identifier)) - .find("AssertionError")!=std::string::npos) - { - assertion_failure=true; - } - const bool use_this(statement!="invokestatic"); + const bool use_this(statement != "invokestatic"); const bool is_virtual( statement=="invokevirtual" || statement=="invokeinterface"); @@ -2107,6 +2154,134 @@ codet java_bytecode_convert_methodt::convert_instructions( c.operands()=op; } + // next we do the exception handling + std::vector exception_ids; + std::vector handler_labels; + + // add the CATCH-PUSH instruction(s) + // be aware of different try-catch blocks with the same starting pc + std::size_t pos=0; + int end_pc=-1; + while(possource_location.get_line().empty()) c.add_source_location()=i_it->source_location; diff --git a/src/java_bytecode/java_bytecode_convert_method_class.h b/src/java_bytecode/java_bytecode_convert_method_class.h index 6844e337f22..263d0c68810 100644 --- a/src/java_bytecode/java_bytecode_convert_method_class.h +++ b/src/java_bytecode/java_bytecode_convert_method_class.h @@ -141,6 +141,7 @@ class java_bytecode_convert_methodt:public messaget exprt::operandst pop(std::size_t n); + void pop_residue(std::size_t n); void push(const exprt::operandst &o); bool is_constructor(const class_typet::methodt &method); From 33c8e3714b9a5efbdc231e71b8c4e5f49f4cc4ed Mon Sep 17 00:00:00 2001 From: Cristina Date: Wed, 14 Dec 2016 15:24:53 +0000 Subject: [PATCH 104/699] Remove throw/try-catch and add the required instrumentation For each function f we record its exceptional return value as variable f#exception_value and each throw/function call is instrumented with assignments involving these variables. Then, the dynamic dispatch of exception handlers is done by using instanceof over such variables. --- regression/exceptions/exceptions1/test.desc | 2 +- .../exceptions/exceptions15/InetAddress.class | Bin 0 -> 251 bytes .../exceptions15/InetSocketAddress.class | Bin 0 -> 263 bytes regression/exceptions/exceptions15/test.class | Bin 0 -> 1006 bytes regression/exceptions/exceptions15/test.desc | 8 + regression/exceptions/exceptions15/test.java | 20 + regression/exceptions/exceptions2/test.desc | 2 +- regression/exceptions/exceptions4/test.class | Bin 743 -> 914 bytes regression/exceptions/exceptions4/test.java | 2 + regression/exceptions/exceptions5/test.class | Bin 997 -> 1198 bytes regression/exceptions/exceptions5/test.java | 45 +- src/cbmc/cbmc_parse_options.cpp | 3 + .../goto_analyzer_parse_options.cpp | 3 + .../goto_instrument_parse_options.cpp | 3 + src/goto-programs/Makefile | 4 +- src/goto-programs/goto_convert.cpp | 80 +++ src/goto-programs/goto_convert_class.h | 4 + src/goto-programs/goto_convert_exceptions.cpp | 67 ++ .../goto_convert_side_effect.cpp | 25 + src/goto-programs/remove_exceptions.cpp | 586 ++++++++++++++++++ src/goto-programs/remove_exceptions.h | 24 + .../java_bytecode_convert_method.cpp | 132 ++-- src/symex/symex_parse_options.cpp | 4 + src/util/irep_ids.txt | 1 - src/util/std_code.h | 1 - 25 files changed, 936 insertions(+), 80 deletions(-) create mode 100644 regression/exceptions/exceptions15/InetAddress.class create mode 100644 regression/exceptions/exceptions15/InetSocketAddress.class create mode 100644 regression/exceptions/exceptions15/test.class create mode 100644 regression/exceptions/exceptions15/test.desc create mode 100644 regression/exceptions/exceptions15/test.java create mode 100644 src/goto-programs/remove_exceptions.cpp create mode 100644 src/goto-programs/remove_exceptions.h diff --git a/regression/exceptions/exceptions1/test.desc b/regression/exceptions/exceptions1/test.desc index baf72e7da81..7c6146907d0 100644 --- a/regression/exceptions/exceptions1/test.desc +++ b/regression/exceptions/exceptions1/test.desc @@ -4,7 +4,7 @@ test.class ^EXIT=10$ ^SIGNAL=0$ ^.*assertion at file test.java line 26 function.*: FAILURE$ -\*\* 1 of 35 failed (2 iterations)$ +\*\* 1 of 4 failed (2 iterations)$ ^VERIFICATION FAILED$ -- ^warning: ignoring diff --git a/regression/exceptions/exceptions15/InetAddress.class b/regression/exceptions/exceptions15/InetAddress.class new file mode 100644 index 0000000000000000000000000000000000000000..3229324e624dde300b6b541750ba938c64539274 GIT binary patch literal 251 zcmYjL%L>9k44i0fwbloIfk*XVFWwYE1VJczP`q#3MOSJI?dpGd5RBA;vM9y`caxp-NG_CFtZ7;3;Za4qX5S)!MscHOZ`v-bd56#7!QV>B9f*vg1Uy?gsTsgIcyWh>;*9Bn6Ea5_wy;6I@t#$?TN)8~h3U z0bWHDNHo!Rf0Xe|S=)kXI(O#YbI+N3W`F$_|cZHLUYcNw*C;NIJq%NwVKMc%#)@86=7l6Vr{gSn8!_ zQ^_=4m}%_!hkiZs-_(AvzwRHjhohYWg~cGs>~S}fmI~x*Xv`>@dFRY1 z9!eObd8> zu`tXv-%i>nbMKu4FoG*Q(MD9bn&#(>7Gth#ePQTr&9_@C=jE)GKwQNbn}l&HBYBpQ zShJTo+#U|A!(nweZlIcRd?vHa8;sX#v!}?N!rnMWdE+bcN9g|n=lvN9zfK4ST$<2F zxS6uT9cYCS8sJ1FW~&r3Q`bmX;%^)`i6(XD0^`{QOzswLbHoYO9a!rQ?vzl#-HyBS jZAoCbTs(z)1jjyxo%@FT|4ti@K3LvMLsZm5udj0q%O9*WOr-yukZ(W z1`{xn$h$wvc%~qP$WC_VyMO09Gr#}*`~_ecbrVx4X_z+=QD@n}0xCMnCKhqafQ2Ou zRTBnEI_5RhOx(sD4R-~y1v?0&A3B~JJa+=SGmt$2u`Up=JFXKx6^ND>)&ycruO|hP zEytB_M#GNu->YDOOv~%qgEiZClzwcCg`b>&HCmwz!WCu@ZO0YJmp`^P>@Rk0V7vWV zJMKnK@ufXvjqJF_S+jt)se%S%EmuCD zwB%{;=785oetR--eAznzO^(759lXPJ%<&;i@xh4Hv>KCA6hg7VJxi^|Q}CRq>_hBO zh~NVE_>mDg%GR-*$3TvUff@Nl@FP*XWFu4USwvAZyJM{nQ Rm}S@mBGxlST7gOg#lQE)sVM*e delta 439 zcmZWlOG*Pl6s(?K&(AoCzeFcv)G=zJ1|$av<4yu@bvcR%L0pO3oIwX%?DK4x$40NOZo;bK!_%Y~+V?7+shMBRm@@Q#aJ>`62p zl20S1E-Q(8Fo%MGNO+HZc<{3`5m%Z%_HiH(^wRsZb(7v+w@xp5SC@C$Otkwp>i{As zD?K9}0!%|YPt>9p^k!oWF=C)0ptXKT6dC)!aS01V4i>RQMty#wTBDC9(9XxuyUl6$ z8Rh`q1QrQ79ine^N4ZGNYf$VWB-ZmX5hNL#$06_K9afk+WPepERQVdUHh(N*g=Iay zlu^lBim-|`Dnec##)(9=kVr%-}2OhKRI6MW_e zcm@+lY$ES|lyRK_Aw)8nv)4ZRa`s;PoZo+b{sPdCIUTJSQ1L=XK*~WKij+e-!cq?F z&@d3e2u3yOG=`TEG-F)FgpO+%&@iZBNW-v-NgWwvRpbPkJ51NL9M7&++$q~N3ngn! zKr9P{$LxyjjSB=*-HQTBuDWIkMDupVny-}$mh(Y63&iu)qFGur9b4*Wn~Jw#yUdaI zEY}-lblJ2k0*Tbe{HD2Wrb}jJJ-y&Lc4d83W*0m(n4hAjC`y!*s31{RB2%J_L_9EP zeUUzY+jUKx0eHwF^8E|9$FCi9QSX~(HLY*{8$@z%gB@&d67&v%7Q ztLR?wkD_m$wDfE$LJuy{)OM*^OSDohxzP z9K@RC+K#n$UNjl=YBX@z%V_7lY2~F8v7~I1C6=9hmZ-0gz*SOcG0LUBO%8UL z^&6RyJbhv=joh^3KKY5!>j64gQIfb5U96xTDjxD2g?f-@r4ZtpK#w1h^HB$5SAEn) zw8M-&^phjn#UnhXe8N8gZ9_$Gf-gTUm#1>+lU+SKA8o%M1vJH*kI=FQRoRCU{DH>* S$1GEZ5HKd?Wq3{{fd0S!tketu delta 581 zcmZXRO-~b16o#LfX*=!hv=q=DdonxX zo}CGjK!S%KzIDn z8}6$|G??=!>~!`!)pwoUt?G+6JDYF!;-+8g&xs0ng_6a~3-C}o=_~PpU!12YsWwQ$@U@HFJxEGh`t?BX?@0A$`t?0BwEKB0Tq3| zv-Q7m%eAerp{oQ~LW^4MLooP$MkMN@-4Nwv`7IGy5n@gLhA6%kJxh9BMAMY%=Z44@ z^m>y4O|eVgQa)giP%@;6BZ_XzOEONLVOP;`-hgUXoL6>7XzvOE~ zZq*&DCeYZ)Ki3qd=E|VECwEHzkT7vXA~?Yu>(O_c{X4a7nZ%Et>R)o#J>R #include #include +#include #include #include #include @@ -894,6 +895,8 @@ bool cbmc_parse_optionst::process_goto_program( cmdline.isset("pointer-check")); // Java virtual functions -> explicit dispatch tables: remove_virtual_functions(symbol_table, goto_functions); + // remove catch and throw + remove_exceptions(symbol_table, goto_functions); // Similar removal of RTTI inspection: remove_instanceof(symbol_table, goto_functions); diff --git a/src/goto-analyzer/goto_analyzer_parse_options.cpp b/src/goto-analyzer/goto_analyzer_parse_options.cpp index 89d3d56731c..e462740c1cc 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.cpp +++ b/src/goto-analyzer/goto_analyzer_parse_options.cpp @@ -19,6 +19,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include #include #include #include @@ -387,6 +388,8 @@ bool goto_analyzer_parse_optionst::process_goto_program( remove_function_pointers(goto_model, cmdline.isset("pointer-check")); // Java virtual functions -> explicit dispatch tables: remove_virtual_functions(goto_model); + // remove Java throw and catch + remove_exceptions(goto_model); // remove rtti remove_instanceof(goto_model); diff --git a/src/goto-instrument/goto_instrument_parse_options.cpp b/src/goto-instrument/goto_instrument_parse_options.cpp index cce5aaad42b..0a322cf299f 100644 --- a/src/goto-instrument/goto_instrument_parse_options.cpp +++ b/src/goto-instrument/goto_instrument_parse_options.cpp @@ -18,6 +18,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include #include #include #include @@ -810,6 +811,8 @@ void goto_instrument_parse_optionst::do_indirect_call_and_rtti_removal( cmdline.isset("pointer-check")); status() << "Virtual function removal" << eom; remove_virtual_functions(symbol_table, goto_functions); + status() << "Catch and throw removal" << eom; + remove_exceptions(symbol_table, goto_functions); status() << "Java instanceof removal" << eom; remove_instanceof(symbol_table, goto_functions); } diff --git a/src/goto-programs/Makefile b/src/goto-programs/Makefile index 8b69282c381..1b303c759b9 100644 --- a/src/goto-programs/Makefile +++ b/src/goto-programs/Makefile @@ -13,8 +13,8 @@ SRC = goto_convert.cpp goto_convert_function_call.cpp \ remove_unused_functions.cpp remove_vector.cpp \ wp.cpp goto_clean_expr.cpp safety_checker.cpp parameter_assignments.cpp \ compute_called_functions.cpp link_to_library.cpp \ - remove_returns.cpp osx_fat_reader.cpp remove_complex.cpp \ - goto_trace.cpp xml_goto_trace.cpp vcd_goto_trace.cpp \ + remove_returns.cpp remove_exceptions.cpp osx_fat_reader.cpp \ + remove_complex.cpp goto_trace.cpp xml_goto_trace.cpp vcd_goto_trace.cpp \ graphml_witness.cpp remove_virtual_functions.cpp \ class_hierarchy.cpp show_goto_functions.cpp get_goto_model.cpp \ slice_global_inits.cpp goto_inline_class.cpp class_identifier.cpp \ diff --git a/src/goto-programs/goto_convert.cpp b/src/goto-programs/goto_convert.cpp index a3124f3b898..58cf6666897 100644 --- a/src/goto-programs/goto_convert.cpp +++ b/src/goto-programs/goto_convert.cpp @@ -47,6 +47,85 @@ static bool is_empty(const goto_programt &goto_program) /*******************************************************************\ +Function: finish_catch_push_targets + + Inputs: + + Outputs: + + Purpose: Populate the CATCH instructions with the targets + corresponding to their associated labels + +\*******************************************************************/ + +static void finish_catch_push_targets(goto_programt &dest) +{ + std::map label_targets; + + // in the first pass collect the labels and the corresponding targets + Forall_goto_program_instructions(it, dest) + { + if(!it->labels.empty()) + { + for(auto label : it->labels) + // record the label and the corresponding target + label_targets.insert(std::make_pair(label, it)); + } + } + + // in the second pass set the targets + Forall_goto_program_instructions(it, dest) + { + if(it->is_catch()) + { + bool handler_added=true; + irept exceptions=it->code.find(ID_exception_list); + + if(exceptions.is_nil() && + it->code.has_operands()) + exceptions=it->code.op0().find(ID_exception_list); + + const irept::subt &exception_list=exceptions.get_sub(); + + if(!exception_list.empty()) + { + // in this case we have a CATCH_PUSH + irept handlers=it->code.find(ID_label); + if(handlers.is_nil() && + it->code.has_operands()) + handlers=it->code.op0().find(ID_label); + const irept::subt &handler_list=handlers.get_sub(); + + // some handlers may not have been converted (if there was no + // exception to be caught); in such a situation we abort + for(const auto &handler : handler_list) + { + if(label_targets.find(handler.id())==label_targets.end()) + { + handler_added=false; + break; + } + } + + if(!handler_added) + continue; + + for(const auto &handler : handler_list) + { + std::map::const_iterator handler_it= + label_targets.find(handler.id()); + assert(handler_it!=label_targets.end()); + // set the target + it->targets.push_back(handler_it->second); + } + } + } + } +} + +/******************************************************************* \ + Function: goto_convertt::finish_gotos Inputs: @@ -302,6 +381,7 @@ void goto_convertt::goto_convert_rec( finish_gotos(dest); finish_computed_gotos(dest); finish_guarded_gotos(dest); + finish_catch_push_targets(dest); } /*******************************************************************\ diff --git a/src/goto-programs/goto_convert_class.h b/src/goto-programs/goto_convert_class.h index feab8197046..05c35efa3c0 100644 --- a/src/goto-programs/goto_convert_class.h +++ b/src/goto-programs/goto_convert_class.h @@ -94,6 +94,9 @@ class goto_convertt:public messaget side_effect_exprt &expr, goto_programt &dest, bool result_is_used); + void remove_push_catch( + side_effect_exprt &expr, + goto_programt &dest); void remove_assignment( side_effect_exprt &expr, goto_programt &dest, @@ -237,6 +240,7 @@ class goto_convertt:public messaget void convert_msc_try_except(const codet &code, goto_programt &dest); void convert_msc_leave(const codet &code, goto_programt &dest); void convert_try_catch(const codet &code, goto_programt &dest); + void convert_java_try_catch(const codet &code, goto_programt &dest); void convert_CPROVER_try_catch(const codet &code, goto_programt &dest); void convert_CPROVER_try_finally(const codet &code, goto_programt &dest); void convert_CPROVER_throw(const codet &code, goto_programt &dest); diff --git a/src/goto-programs/goto_convert_exceptions.cpp b/src/goto-programs/goto_convert_exceptions.cpp index 8d04f3cca16..63f503e8a0b 100644 --- a/src/goto-programs/goto_convert_exceptions.cpp +++ b/src/goto-programs/goto_convert_exceptions.cpp @@ -128,6 +128,73 @@ void goto_convertt::convert_msc_leave( /*******************************************************************\ +Function: goto_convertt::convert_java_try_catch + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void goto_convertt::convert_java_try_catch( + const codet &code, + goto_programt &dest) +{ + assert(!code.operands().empty()); + + // add the CATCH instruction to 'dest' + goto_programt::targett catch_instruction=dest.add_instruction(); + catch_instruction->make_catch(); + catch_instruction->code.set_statement(ID_catch); + catch_instruction->source_location=code.source_location(); + catch_instruction->function=code.source_location().get_function(); + + // the CATCH instruction is annotated with a list of exception IDs + const irept exceptions=code.op0().find(ID_exception_list); + if(exceptions.is_not_nil()) + { + irept::subt exceptions_sub=exceptions.get_sub(); + irept::subt &exception_list= + catch_instruction->code.add(ID_exception_list).get_sub(); + exception_list.resize(exceptions_sub.size()); + for(size_t i=0; icode.add(ID_label).get_sub(); + handlers_list.resize(handlers_sub.size()); + for(size_t i=0; icode.get_sub().resize(1); + catch_instruction->code.get_sub()[0]=code.op0().op0(); + } + + // add a SKIP target for the end of everything + goto_programt end; + goto_programt::targett end_target=end.add_instruction(); + end_target->make_skip(); + end_target->source_location=code.source_location(); + end_target->function=code.source_location().get_function(); + + // add the end-target + dest.destructive_append(end); +} + +/*******************************************************************\ + Function: goto_convertt::convert_try_catch Inputs: diff --git a/src/goto-programs/goto_convert_side_effect.cpp b/src/goto-programs/goto_convert_side_effect.cpp index f34ee9d03a0..dbebb856ec1 100644 --- a/src/goto-programs/goto_convert_side_effect.cpp +++ b/src/goto-programs/goto_convert_side_effect.cpp @@ -767,6 +767,29 @@ void goto_convertt::remove_statement_expression( /*******************************************************************\ +Function: goto_convertt::remove_push_catch + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void goto_convertt::remove_push_catch( + side_effect_exprt &expr, + goto_programt &dest) +{ + // we only get here for ID_push_catch, which is only used for Java + convert_java_try_catch(code_expressiont(expr), dest); + + // the result can't be used, these are void + expr.make_nil(); +} + +/*******************************************************************\ + Function: goto_convertt::remove_side_effect Inputs: @@ -837,6 +860,8 @@ void goto_convertt::remove_side_effect( // the result can't be used, these are void expr.make_nil(); } + else if(statement==ID_push_catch) + remove_push_catch(expr, dest); else { error().source_location=expr.find_source_location(); diff --git a/src/goto-programs/remove_exceptions.cpp b/src/goto-programs/remove_exceptions.cpp new file mode 100644 index 00000000000..14700921e24 --- /dev/null +++ b/src/goto-programs/remove_exceptions.cpp @@ -0,0 +1,586 @@ +/*******************************************************************\ + +Module: Remove exception handling + +Author: Cristina David + +Date: December 2016 + +\*******************************************************************/ +#define DEBUG +#ifdef DEBUG +#include +#endif +#include + +#include +#include + +#include "remove_exceptions.h" + +class remove_exceptionst +{ + typedef std::vector> catch_handlerst; + typedef std::vector stack_catcht; + +public: + explicit remove_exceptionst(symbol_tablet &_symbol_table): + symbol_table(_symbol_table) + { + } + + void operator()( + goto_functionst &goto_functions); + +protected: + symbol_tablet &symbol_table; + + void add_exceptional_returns( + const goto_functionst::function_mapt::iterator &); + + void replace_throws( + const goto_functionst::function_mapt::iterator &); + + void instrument_function_calls( + const goto_functionst::function_mapt::iterator &); + + void instrument_exception_handlers( + const goto_functionst::function_mapt::iterator &); + + void add_gotos( + const goto_functionst::function_mapt::iterator &); + + void add_throw_gotos( + const goto_functionst::function_mapt::iterator &, + const goto_programt::instructionst::iterator &, + const stack_catcht &); + + void add_function_call_gotos( + const goto_functionst::function_mapt::iterator &, + const goto_programt::instructionst::iterator &, + const stack_catcht &); +}; + +/*******************************************************************\ + +Function: remove_exceptionst::add_exceptional_returns + +Inputs: + +Outputs: + +Purpose: adds exceptional return variables for every function that + may escape exceptions + +\*******************************************************************/ + +void remove_exceptionst::add_exceptional_returns( + const goto_functionst::function_mapt::iterator &func_it) +{ + const irep_idt &function_id=func_it->first; + goto_programt &goto_program=func_it->second.body; + + assert(symbol_table.has_symbol(function_id)); + const symbolt &function_symbol=symbol_table.lookup(function_id); + + // for now only add exceptional returns for Java + if(function_symbol.mode!=ID_java) + return; + + if(goto_program.empty()) + return; + + // We generate an exceptional return value for any function that has + // a throw or a function call. This can be improved by only considering + // function calls that may escape exceptions. However, this will + // require multiple passes. + bool add_exceptional_var=false; + Forall_goto_program_instructions(instr_it, goto_program) + if(instr_it->is_throw() || instr_it->is_function_call()) + { + add_exceptional_var=true; + break; + } + + if(add_exceptional_var) + { + // look up the function symbol + symbol_tablet::symbolst::iterator s_it= + symbol_table.symbols.find(function_id); + + assert(s_it!=symbol_table.symbols.end()); + + auxiliary_symbolt new_symbol; + new_symbol.is_static_lifetime=true; + new_symbol.module=function_symbol.module; + new_symbol.base_name=id2string(function_symbol.base_name)+EXC_SUFFIX; + new_symbol.name=id2string(function_symbol.name)+EXC_SUFFIX; + new_symbol.mode=function_symbol.mode; + new_symbol.type=typet(ID_pointer, empty_typet()); + symbol_table.add(new_symbol); + + // initialize the exceptional return with NULL + symbol_exprt lhs_expr_null=new_symbol.symbol_expr(); + exprt rhs_expr_null; + rhs_expr_null=null_pointer_exprt(pointer_typet(empty_typet())); + goto_programt::targett t_null= + goto_program.insert_before(goto_program.instructions.begin()); + t_null->make_assignment(); + t_null->source_location= + goto_program.instructions.begin()->source_location; + t_null->code=code_assignt( + lhs_expr_null, + rhs_expr_null); + t_null->function=function_id; + } + return; +} + +/*******************************************************************\ + +Function: remove_exceptionst::replace_throws + +Inputs: + +Outputs: + +Purpose: turns 'throw x' in function f into an assignment to f#exc_value + +\*******************************************************************/ + +void remove_exceptionst::replace_throws( + const goto_functionst::function_mapt::iterator &func_it) +{ + const irep_idt &function_id=func_it->first; + goto_programt &goto_program=func_it->second.body; + + if(goto_program.empty()) + return; + + Forall_goto_program_instructions(instr_it, goto_program) + { + if(instr_it->is_throw() && + symbol_table.has_symbol(id2string(function_id)+EXC_SUFFIX)) + { + assert(instr_it->code.operands().size()==1); + const symbolt &exc_symbol= + symbol_table.lookup(id2string(function_id)+EXC_SUFFIX); + + // replace "throw x;" by "f#exception_value=x;" + symbol_exprt lhs_expr=exc_symbol.symbol_expr(); + // find the symbol corresponding to the thrown exceptions + exprt exc_expr=instr_it->code; + while(exc_expr.id()!=ID_symbol && exc_expr.has_operands()) + exc_expr=exc_expr.op0(); + + // add the assignment with the appropriate cast + code_assignt assignment(typecast_exprt(lhs_expr, exc_expr.type()), + exc_expr); + // now turn the `throw' into `assignment' + instr_it->type=ASSIGN; + instr_it->code=assignment; + } + } +} + +/*******************************************************************\ + +Function: remove_exceptionst::instrument_function_calls + +Inputs: + +Outputs: + +Purpose: after each function call g() in function f + adds f#exception_value=g#exception_value; + +\*******************************************************************/ + +void remove_exceptionst::instrument_function_calls( + const goto_functionst::function_mapt::iterator &func_it) +{ + const irep_idt &caller_id=func_it->first; + goto_programt &goto_program=func_it->second.body; + + if(goto_program.empty()) + return; + + Forall_goto_program_instructions(instr_it, goto_program) + { + if(instr_it->is_function_call()) + { + code_function_callt &function_call=to_code_function_call(instr_it->code); + const irep_idt &callee_id= + to_symbol_expr(function_call.function()).get_identifier(); + + // can exceptions escape? + if(symbol_table.has_symbol(id2string(callee_id)+EXC_SUFFIX) && + symbol_table.has_symbol(id2string(caller_id)+EXC_SUFFIX)) + { + const symbolt &callee= + symbol_table.lookup(id2string(callee_id)+EXC_SUFFIX); + const symbolt &caller= + symbol_table.lookup(id2string(caller_id)+EXC_SUFFIX); + + symbol_exprt rhs_expr=callee.symbol_expr(); + symbol_exprt lhs_expr=caller.symbol_expr(); + + goto_programt::targett t=goto_program.insert_after(instr_it); + t->make_assignment(); + t->source_location=instr_it->source_location; + t->code=code_assignt(lhs_expr, rhs_expr); + t->function=instr_it->function; + } + } + } +} + +/*******************************************************************\ + +Function: remove_exceptionst::instrument_exception_handlers + +Inputs: + +Outputs: + +Purpose: at the beginning of each handler in function f + adds exc=f#exception_value; f#exception_value=NULL; + +\*******************************************************************/ + +void remove_exceptionst::instrument_exception_handlers( + const goto_functionst::function_mapt::iterator &func_it) +{ + const irep_idt &function_id=func_it->first; + goto_programt &goto_program=func_it->second.body; + + if(goto_program.empty()) + return; + + Forall_goto_program_instructions(instr_it, goto_program) + { + // is this a handler + if(instr_it->type==CATCH && instr_it->code.has_operands()) + { + // retrieve the exception variable + const irept &exception=instr_it->code.op0(); + + if(symbol_table.has_symbol(id2string(function_id)+EXC_SUFFIX)) + { + const symbolt &function_symbol= + symbol_table.lookup(id2string(function_id)+EXC_SUFFIX); + // next we reset the exceptional return to NULL + symbol_exprt lhs_expr_null=function_symbol.symbol_expr(); + exprt rhs_expr_null; + rhs_expr_null=null_pointer_exprt(pointer_typet(empty_typet())); + + // add the assignment + goto_programt::targett t_null=goto_program.insert_after(instr_it); + t_null->make_assignment(); + t_null->source_location=instr_it->source_location; + t_null->code=code_assignt( + lhs_expr_null, + rhs_expr_null); + t_null->function=instr_it->function; + + // add the assignment exc=f#exception_value + symbol_exprt rhs_expr_exc=function_symbol.symbol_expr(); + + const exprt &lhs_expr_exc=static_cast(exception); + goto_programt::targett t_exc=goto_program.insert_after(instr_it); + t_exc->make_assignment(); + t_exc->source_location=instr_it->source_location; + t_exc->code=code_assignt( + typecast_exprt(lhs_expr_exc, rhs_expr_exc.type()), + rhs_expr_exc); + t_exc->function=instr_it->function; + } + + instr_it->make_skip(); + } + } +} + +/*******************************************************************\ + +Function: remove_exceptionst::add_gotos_throw + +Inputs: + +Outputs: + +Purpose: instruments each throw with conditional GOTOS to the + corresponding exception handlers + +\*******************************************************************/ + +void remove_exceptionst::add_throw_gotos( + const goto_functionst::function_mapt::iterator &func_it, + const goto_programt::instructionst::iterator &instr_it, + const remove_exceptionst::stack_catcht &stack_catch) +{ + assert(instr_it->type==THROW); + + goto_programt &goto_program=func_it->second.body; + + assert(instr_it->code.operands().size()==1); + + // find the end of the function + goto_programt::targett end_function; + for(end_function=instr_it; + !end_function->is_end_function(); + end_function++) {} + if(end_function!=instr_it) + { + // jump to the end of the function + // this will appear after the GOTO-based dynamic dispatch below + goto_programt::targett t_end=goto_program.insert_after(instr_it); + t_end->make_goto(end_function); + t_end->source_location=instr_it->source_location; + t_end->function=instr_it->function; + } + + // add GOTOs implementing the dynamic dispatch of the + // exception handlers + for(std::size_t i=stack_catch.size(); i-->0;) + { + for(std::size_t j=stack_catch[i].size(); j-->0;) + { + goto_programt::targett new_state_pc= + stack_catch[i][j].second; + + // find handler + goto_programt::targett t_exc=goto_program.insert_after(instr_it); + t_exc->make_goto(new_state_pc); + t_exc->source_location=instr_it->source_location; + t_exc->function=instr_it->function; + + // use instanceof to check that this is the correct handler + symbol_typet type(stack_catch[i][j].first); + type_exprt expr(type); + // find the symbol corresponding to the caught exceptions + exprt exc_symbol=instr_it->code; + while(exc_symbol.id()!=ID_symbol) + exc_symbol=exc_symbol.op0(); + + binary_predicate_exprt check(exc_symbol, ID_java_instanceof, expr); + t_exc->guard=check; + } + } +} + +/*******************************************************************\ + +Function: remove_exceptionst::add_function_call_gotos + +Inputs: + +Outputs: + +Purpose: instruments each function call that may escape exceptions + with conditional GOTOS to the corresponding exception handlers + +\*******************************************************************/ + +void remove_exceptionst::add_function_call_gotos( + const goto_functionst::function_mapt::iterator &func_it, + const goto_programt::instructionst::iterator &instr_it, + const stack_catcht &stack_catch) +{ + assert(instr_it->type==FUNCTION_CALL); + + goto_programt &goto_program=func_it->second.body; + + // save the address of the next instruction + goto_programt::instructionst::iterator next_it=instr_it; + next_it++; + + code_function_callt &function_call=to_code_function_call(instr_it->code); + assert(function_call.function().id()==ID_symbol); + const irep_idt &callee_id= + to_symbol_expr(function_call.function()).get_identifier(); + + if(symbol_table.has_symbol(id2string(callee_id)+EXC_SUFFIX)) + { + // dynamic dispatch of the escaped exception + const symbolt &callee_exc_symbol= + symbol_table.lookup(id2string(callee_id)+EXC_SUFFIX); + symbol_exprt callee_exc=callee_exc_symbol.symbol_expr(); + + for(std::size_t i=stack_catch.size(); i-->0;) + { + for(std::size_t j=stack_catch[i].size(); j-->0;) + { + goto_programt::targett new_state_pc; + new_state_pc=stack_catch[i][j].second; + goto_programt::targett t_exc=goto_program.insert_after(instr_it); + t_exc->make_goto(new_state_pc); + t_exc->source_location=instr_it->source_location; + t_exc->function=instr_it->function; + // use instanceof to check that this is the correct handler + symbol_typet type(stack_catch[i][j].first); + type_exprt expr(type); + binary_predicate_exprt check_instanceof( + callee_exc, + ID_java_instanceof, + expr); + t_exc->guard=check_instanceof; + } + } + + // add a null check (so that instanceof can be applied) + equal_exprt eq_null( + callee_exc, + null_pointer_exprt(pointer_typet(empty_typet()))); + // jump to the next instruction + goto_programt::targett t_null=goto_program.insert_after(instr_it); + t_null->make_goto(next_it); + t_null->source_location=instr_it->source_location; + t_null->function=instr_it->function; + t_null->guard=eq_null; + } +} + +/*******************************************************************\ + +Function: remove_exceptionst::add_gotos + +Inputs: + +Outputs: + +Purpose: instruments each throw and function calls that may escape exceptions + with conditional GOTOS to the corresponding exception handlers + +\*******************************************************************/ + +void remove_exceptionst::add_gotos( + const goto_functionst::function_mapt::iterator &func_it) +{ + // Stack of try-catch blocks + stack_catcht stack_catch; + + goto_programt &goto_program=func_it->second.body; + + if(goto_program.empty()) + return; + Forall_goto_program_instructions(instr_it, goto_program) + { + // it's a CATCH but not a handler + if(instr_it->type==CATCH && !instr_it->code.has_operands()) + { + if(instr_it->targets.empty()) // pop + { + // pop from the stack if possible + if(!stack_catch.empty()) + { + stack_catch.pop_back(); + } + else + { +#ifdef DEBUG + std::cout << "Remove exceptions: empty stack" << std::endl; +#endif + } + } + else // push + { + remove_exceptionst::catch_handlerst exception; + stack_catch.push_back(exception); + remove_exceptionst::catch_handlerst &last_exception= + stack_catch.back(); + + // copy targets + const irept::subt &exception_list= + instr_it->code.find(ID_exception_list).get_sub(); + assert(exception_list.size()==instr_it->targets.size()); + + // Fill the map with the catch type and the target + unsigned i=0; + for(auto target : instr_it->targets) + { + last_exception.push_back( + std::make_pair(exception_list[i].id(), target)); + i++; + } + } + + instr_it->make_skip(); + } + else if(instr_it->type==THROW) + { + add_throw_gotos(func_it, instr_it, stack_catch); + } + else if(instr_it->type==FUNCTION_CALL) + { + add_function_call_gotos(func_it, instr_it, stack_catch); + } + } +} + + +/*******************************************************************\ + +Function: remove_exceptionst::operator() + +Inputs: + +Outputs: + +Purpose: + +\*******************************************************************/ + +void remove_exceptionst::operator()(goto_functionst &goto_functions) +{ + Forall_goto_functions(it, goto_functions) + { + add_exceptional_returns(it); + } + Forall_goto_functions(it, goto_functions) + { + instrument_exception_handlers(it); + add_gotos(it); + instrument_function_calls(it); + replace_throws(it); + } +} + +/*******************************************************************\ + +Function: remove_exceptions + +Inputs: + +Outputs: + +Purpose: removes throws/CATCH-POP/CATCH-PUSH + +\*******************************************************************/ + +void remove_exceptions( + symbol_tablet &symbol_table, + goto_functionst &goto_functions) +{ + remove_exceptionst remove_exceptions(symbol_table); + remove_exceptions(goto_functions); +} + +/*******************************************************************\ + +Function: remove_exceptions + +Inputs: + +Outputs: + +Purpose: removes throws/CATCH-POP/CATCH-PUSH + +\*******************************************************************/ + +void remove_exceptions(goto_modelt &goto_model) +{ + remove_exceptionst remove_exceptions(goto_model.symbol_table); + remove_exceptions(goto_model.goto_functions); +} diff --git a/src/goto-programs/remove_exceptions.h b/src/goto-programs/remove_exceptions.h new file mode 100644 index 00000000000..89162b5833d --- /dev/null +++ b/src/goto-programs/remove_exceptions.h @@ -0,0 +1,24 @@ +/*******************************************************************\ + +Module: Remove function exceptional returns + +Author: Cristina David + +Date: December 2016 + +\*******************************************************************/ + +#ifndef CPROVER_GOTO_PROGRAMS_REMOVE_EXCEPTIONS_H +#define CPROVER_GOTO_PROGRAMS_REMOVE_EXCEPTIONS_H + +#include + +#define EXC_SUFFIX "#exception_value" + +// Removes 'throw x' and CATCH-PUSH/CATCH-POP +// and adds the required instrumentation (GOTOs and assignments) + +void remove_exceptions(symbol_tablet &, goto_functionst &); +void remove_exceptions(goto_modelt &); + +#endif diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 6f816424354..44afd69b72a 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -157,9 +157,21 @@ exprt::operandst java_bytecode_convert_methodt::pop(std::size_t n) return operands; } +/*******************************************************************\ + +Function: java_bytecode_convert_methodt::pop_residue + +Inputs: + +Outputs: + +Purpose: removes minimum(n, stack.size()) elements from the stack + +\*******************************************************************/ + void java_bytecode_convert_methodt::pop_residue(std::size_t n) { - std::size_t residue_size=n<=stack.size()?n:stack.size(); + std::size_t residue_size=std::min(n, stack.size()); stack.resize(stack.size()-residue_size); } @@ -853,8 +865,10 @@ static void gather_symbol_live_ranges( } } else + { forall_operands(it, e) gather_symbol_live_ranges(pc, *it, result); + } } /*******************************************************************\ @@ -960,18 +974,20 @@ codet java_bytecode_convert_methodt::convert_instructions( if(i_it->statement=="athrow" || i_it->statement=="invokestatic" || - i_it->statement=="invokevirtual") + i_it->statement=="invokevirtual" || + i_it->statement=="invokespecial" || + i_it->statement=="invokeinterface") { // find the corresponding try-catch blocks and add the handlers // to the targets - for(std::size_t e=0; eaddress>=method.exception_table[e].start_pc && - i_it->addressaddress>=exception_row.start_pc && + i_it->addresssecond.successors.push_back( - method.exception_table[e].handler_pc); - targets.insert(method.exception_table[e].handler_pc); + exception_row.handler_pc); + targets.insert(exception_row.handler_pc); } } } @@ -1109,7 +1125,7 @@ codet java_bytecode_convert_methodt::convert_instructions( exprt exc_var=variable( arg0, statement[0], i_it->address, - false); + NO_CAST); // throw away the operands pop_residue(bytecode_info.pop); @@ -1118,17 +1134,19 @@ codet java_bytecode_convert_methodt::convert_instructions( side_effect_expr_catcht catch_handler_expr; // pack the exception variable so that it can be used // later for instrumentation - catch_handler_expr.set(ID_handler, exc_var); + catch_handler_expr.get_sub().resize(1); + catch_handler_expr.get_sub()[0]=exc_var; + codet catch_handler=code_expressiont(catch_handler_expr); + code_labelt newlabel(label(std::to_string(cur_pc)), + code_blockt()); - code_labelt newlabel(label(i2string(cur_pc)), code_blockt()); code_blockt label_block=to_code_block(newlabel.code()); code_blockt handler_block; handler_block.move_to_operands(c); handler_block.move_to_operands(catch_handler); handler_block.move_to_operands(label_block); c=handler_block; - break; } } @@ -1151,11 +1169,30 @@ codet java_bytecode_convert_methodt::convert_instructions( else if(statement=="athrow") { assert(op.size()==1 && results.size()==1); + code_blockt block; + if(!disable_runtime_checks) + { + // TODO throw NullPointerException instead + const typecast_exprt lhs(op[0], pointer_typet(empty_typet())); + const exprt rhs(null_pointer_exprt(to_pointer_type(lhs.type()))); + const exprt not_equal_null( + binary_relation_exprt(lhs, ID_notequal, rhs)); + code_assertt check(not_equal_null); + check.add_source_location() + .set_comment("Throw null"); + check.add_source_location() + .set_property_class("null-pointer-exception"); + block.move_to_operands(check); + } + side_effect_expr_throwt throw_expr; throw_expr.add_source_location()=i_it->source_location; throw_expr.copy_to_operands(op[0]); c=code_expressiont(throw_expr); results[0]=op[0]; + + block.move_to_operands(c); + c=block; } else if(statement=="checkcast") { @@ -1221,7 +1258,7 @@ codet java_bytecode_convert_methodt::convert_instructions( statement=="invokevirtual" || statement=="invokestatic") { - const bool use_this(statement != "invokestatic"); + const bool use_this(statement!="invokestatic"); const bool is_virtual( statement=="invokevirtual" || statement=="invokeinterface"); @@ -2161,17 +2198,19 @@ codet java_bytecode_convert_methodt::convert_instructions( // add the CATCH-PUSH instruction(s) // be aware of different try-catch blocks with the same starting pc std::size_t pos=0; - int end_pc=-1; + size_t end_pc=0; while(possource_location.get_line().empty()) c.add_source_location()=i_it->source_location; @@ -2293,6 +2309,18 @@ codet java_bytecode_convert_methodt::convert_instructions( address_mapt::iterator a_it2=address_map.find(address); assert(a_it2!=address_map.end()); + // we don't worry about exception handlers as we don't load the + // operands from the stack anyway -- we keep explicit global + // exception variables + for(const auto &exception_row : method.exception_table) + { + if(address==exception_row.handler_pc) + { + stack.clear(); + break; + } + } + if(!stack.empty() && a_it2->second.predecessors.size()>1) { // copy into temporaries @@ -2357,8 +2385,6 @@ codet java_bytecode_convert_methodt::convert_instructions( } } - // TODO: add exception handlers from exception table - // review successor computation of athrow! code_blockt code; // Add anonymous locals to the symtab: diff --git a/src/symex/symex_parse_options.cpp b/src/symex/symex_parse_options.cpp index 2ed3fedc518..54aa9382759 100644 --- a/src/symex/symex_parse_options.cpp +++ b/src/symex/symex_parse_options.cpp @@ -32,6 +32,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include #include #include @@ -369,6 +370,9 @@ bool symex_parse_optionst::process_goto_program(const optionst &options) remove_vector(goto_model); // Java virtual functions -> explicit dispatch tables: remove_virtual_functions(goto_model); + // Java throw and catch -> explicit exceptional return variables: + remove_exceptions(goto_model); + // Java instanceof -> clsid comparison: remove_instanceof(goto_model); rewrite_union(goto_model); adjust_float_expressions(goto_model); diff --git a/src/util/irep_ids.txt b/src/util/irep_ids.txt index dca7a814276..b9d2d253538 100644 --- a/src/util/irep_ids.txt +++ b/src/util/irep_ids.txt @@ -740,7 +740,6 @@ java_super_method_call skip_initialize java_enum_static_unwind push_catch -handler string_constraint string_not_contains_constraint cprover_char_literal_func diff --git a/src/util/std_code.h b/src/util/std_code.h index ed1f8f28b74..eb7982f3bbd 100644 --- a/src/util/std_code.h +++ b/src/util/std_code.h @@ -1130,7 +1130,6 @@ class side_effect_expr_catcht:public side_effect_exprt inline side_effect_expr_catcht():side_effect_exprt(ID_push_catch) { } - // TODO: change to ID_catch inline explicit side_effect_expr_catcht(const irept &exception_list): side_effect_exprt(ID_push_catch) { From 05f223359db5bb9b17c0fbf17faaff5ea7ffd9bb Mon Sep 17 00:00:00 2001 From: Cristina Date: Wed, 15 Feb 2017 14:20:28 +0000 Subject: [PATCH 105/699] Moved Java exceptions regression tests These tests are now under cbmc-java. --- .../cbmc-java/NullPointer3/NullPointer3.class | Bin 270 -> 380 bytes .../cbmc-java/NullPointer3/NullPointer3.java | 1 - regression/cbmc-java/NullPointer3/test.desc | 4 ++-- .../exceptions1/A.class | Bin .../exceptions1/B.class | Bin .../exceptions1/C.class | Bin .../exceptions1/D.class | Bin .../exceptions1/test.class | Bin .../exceptions1/test.desc | 2 +- .../exceptions1/test.java | 0 .../exceptions10/A.class | Bin .../exceptions10/B.class | Bin .../exceptions10/C.class | Bin .../exceptions10/test.class | Bin .../exceptions10/test.desc | 0 .../exceptions10/test.java | 0 .../exceptions11/A.class | Bin .../exceptions11/B.class | Bin .../exceptions11/test.class | Bin .../exceptions11/test.desc | 0 .../exceptions11/test.java | 0 .../exceptions12/A.class | Bin .../exceptions12/B.class | Bin .../exceptions12/C.class | Bin .../exceptions12/F.class | Bin .../exceptions12/test.class | Bin .../exceptions12/test.desc | 0 .../exceptions12/test.java | 0 .../exceptions13/A.class | Bin .../exceptions13/B.class | Bin .../exceptions13/C.class | Bin .../exceptions13/F.class | Bin .../exceptions13/test.class | Bin .../exceptions13/test.desc | 0 .../exceptions13/test.java | 0 .../exceptions14/A.class | Bin .../exceptions14/B.class | Bin .../exceptions14/C.class | Bin .../exceptions14/test.class | Bin .../exceptions14/test.desc | 0 .../exceptions14/test.java | 0 .../exceptions15/InetAddress.class | Bin .../exceptions15/InetSocketAddress.class | Bin .../exceptions15/test.class | Bin .../exceptions15/test.desc | 0 .../exceptions15/test.java | 0 .../exceptions16}/A.class | Bin .../exceptions16}/B.class | Bin .../exceptions16}/C.class | Bin regression/cbmc-java/exceptions16/test.class | Bin 0 -> 718 bytes regression/cbmc-java/exceptions16/test.desc | 9 ++++++++ regression/cbmc-java/exceptions16/test.java | 21 ++++++++++++++++++ .../exceptions2/A.class | Bin .../exceptions2}/B.class | Bin .../exceptions2}/C.class | Bin .../exceptions2/test.class | Bin .../exceptions2/test.desc | 2 +- .../exceptions2/test.java | 0 .../exceptions3/A.class | Bin .../exceptions3}/B.class | Bin .../exceptions3}/C.class | Bin .../exceptions3/test.class | Bin .../exceptions3/test.desc | 0 .../exceptions3/test.java | 0 .../exceptions4/A.class | Bin .../exceptions4}/B.class | Bin .../exceptions4}/C.class | Bin .../exceptions4/test.class | Bin .../exceptions4/test.desc | 0 .../exceptions4/test.java | 0 .../exceptions5/A.class | Bin .../exceptions5}/B.class | Bin .../exceptions5}/C.class | Bin .../exceptions5/D.class | Bin .../exceptions5/test.class | Bin .../exceptions5/test.desc | 0 .../exceptions5/test.java | 0 .../exceptions6/A.class | Bin .../exceptions6/B.class | Bin .../exceptions6/C.class | Bin .../exceptions6/D.class | Bin .../exceptions6/test.class | Bin .../exceptions6/test.desc | 0 .../exceptions6/test.java | 0 .../exceptions7}/A.class | Bin .../exceptions7}/B.class | Bin .../exceptions7}/C.class | Bin .../exceptions7/test.class | Bin .../exceptions7/test.desc | 0 .../exceptions7/test.java | 0 regression/cbmc-java/exceptions8/A.class | Bin 0 -> 241 bytes regression/cbmc-java/exceptions8/B.class | Bin 0 -> 216 bytes .../exceptions8}/C.class | Bin .../exceptions8/test.class | Bin .../exceptions8/test.desc | 0 .../exceptions8/test.java | 0 .../exceptions9/A.class | Bin .../exceptions9/B.class | Bin regression/cbmc-java/exceptions9/C.class | Bin 0 -> 216 bytes .../exceptions9/test.class | Bin .../exceptions9/test.desc | 0 .../exceptions9/test.java | 0 regression/exceptions/Makefile | 14 ------------ 103 files changed, 34 insertions(+), 19 deletions(-) rename regression/{exceptions => cbmc-java}/exceptions1/A.class (100%) rename regression/{exceptions => cbmc-java}/exceptions1/B.class (100%) rename regression/{exceptions => cbmc-java}/exceptions1/C.class (100%) rename regression/{exceptions => cbmc-java}/exceptions1/D.class (100%) rename regression/{exceptions => cbmc-java}/exceptions1/test.class (100%) rename regression/{exceptions => cbmc-java}/exceptions1/test.desc (80%) rename regression/{exceptions => cbmc-java}/exceptions1/test.java (100%) rename regression/{exceptions => cbmc-java}/exceptions10/A.class (100%) rename regression/{exceptions => cbmc-java}/exceptions10/B.class (100%) rename regression/{exceptions => cbmc-java}/exceptions10/C.class (100%) rename regression/{exceptions => cbmc-java}/exceptions10/test.class (100%) rename regression/{exceptions => cbmc-java}/exceptions10/test.desc (100%) rename regression/{exceptions => cbmc-java}/exceptions10/test.java (100%) rename regression/{exceptions => cbmc-java}/exceptions11/A.class (100%) rename regression/{exceptions => cbmc-java}/exceptions11/B.class (100%) rename regression/{exceptions => cbmc-java}/exceptions11/test.class (100%) rename regression/{exceptions => cbmc-java}/exceptions11/test.desc (100%) rename regression/{exceptions => cbmc-java}/exceptions11/test.java (100%) rename regression/{exceptions => cbmc-java}/exceptions12/A.class (100%) rename regression/{exceptions => cbmc-java}/exceptions12/B.class (100%) rename regression/{exceptions => cbmc-java}/exceptions12/C.class (100%) rename regression/{exceptions => cbmc-java}/exceptions12/F.class (100%) rename regression/{exceptions => cbmc-java}/exceptions12/test.class (100%) rename regression/{exceptions => cbmc-java}/exceptions12/test.desc (100%) rename regression/{exceptions => cbmc-java}/exceptions12/test.java (100%) rename regression/{exceptions => cbmc-java}/exceptions13/A.class (100%) rename regression/{exceptions => cbmc-java}/exceptions13/B.class (100%) rename regression/{exceptions => cbmc-java}/exceptions13/C.class (100%) rename regression/{exceptions => cbmc-java}/exceptions13/F.class (100%) rename regression/{exceptions => cbmc-java}/exceptions13/test.class (100%) rename regression/{exceptions => cbmc-java}/exceptions13/test.desc (100%) rename regression/{exceptions => cbmc-java}/exceptions13/test.java (100%) rename regression/{exceptions => cbmc-java}/exceptions14/A.class (100%) rename regression/{exceptions => cbmc-java}/exceptions14/B.class (100%) rename regression/{exceptions => cbmc-java}/exceptions14/C.class (100%) rename regression/{exceptions => cbmc-java}/exceptions14/test.class (100%) rename regression/{exceptions => cbmc-java}/exceptions14/test.desc (100%) rename regression/{exceptions => cbmc-java}/exceptions14/test.java (100%) rename regression/{exceptions => cbmc-java}/exceptions15/InetAddress.class (100%) rename regression/{exceptions => cbmc-java}/exceptions15/InetSocketAddress.class (100%) rename regression/{exceptions => cbmc-java}/exceptions15/test.class (100%) rename regression/{exceptions => cbmc-java}/exceptions15/test.desc (100%) rename regression/{exceptions => cbmc-java}/exceptions15/test.java (100%) rename regression/{exceptions/exceptions7 => cbmc-java/exceptions16}/A.class (100%) rename regression/{exceptions/exceptions2 => cbmc-java/exceptions16}/B.class (100%) rename regression/{exceptions/exceptions2 => cbmc-java/exceptions16}/C.class (100%) create mode 100644 regression/cbmc-java/exceptions16/test.class create mode 100644 regression/cbmc-java/exceptions16/test.desc create mode 100644 regression/cbmc-java/exceptions16/test.java rename regression/{exceptions => cbmc-java}/exceptions2/A.class (100%) rename regression/{exceptions/exceptions3 => cbmc-java/exceptions2}/B.class (100%) rename regression/{exceptions/exceptions3 => cbmc-java/exceptions2}/C.class (100%) rename regression/{exceptions => cbmc-java}/exceptions2/test.class (100%) rename regression/{exceptions => cbmc-java}/exceptions2/test.desc (79%) rename regression/{exceptions => cbmc-java}/exceptions2/test.java (100%) rename regression/{exceptions => cbmc-java}/exceptions3/A.class (100%) rename regression/{exceptions/exceptions4 => cbmc-java/exceptions3}/B.class (100%) rename regression/{exceptions/exceptions4 => cbmc-java/exceptions3}/C.class (100%) rename regression/{exceptions => cbmc-java}/exceptions3/test.class (100%) rename regression/{exceptions => cbmc-java}/exceptions3/test.desc (100%) rename regression/{exceptions => cbmc-java}/exceptions3/test.java (100%) rename regression/{exceptions => cbmc-java}/exceptions4/A.class (100%) rename regression/{exceptions/exceptions5 => cbmc-java/exceptions4}/B.class (100%) rename regression/{exceptions/exceptions5 => cbmc-java/exceptions4}/C.class (100%) rename regression/{exceptions => cbmc-java}/exceptions4/test.class (100%) rename regression/{exceptions => cbmc-java}/exceptions4/test.desc (100%) rename regression/{exceptions => cbmc-java}/exceptions4/test.java (100%) rename regression/{exceptions => cbmc-java}/exceptions5/A.class (100%) rename regression/{exceptions/exceptions7 => cbmc-java/exceptions5}/B.class (100%) rename regression/{exceptions/exceptions7 => cbmc-java/exceptions5}/C.class (100%) rename regression/{exceptions => cbmc-java}/exceptions5/D.class (100%) rename regression/{exceptions => cbmc-java}/exceptions5/test.class (100%) rename regression/{exceptions => cbmc-java}/exceptions5/test.desc (100%) rename regression/{exceptions => cbmc-java}/exceptions5/test.java (100%) rename regression/{exceptions => cbmc-java}/exceptions6/A.class (100%) rename regression/{exceptions => cbmc-java}/exceptions6/B.class (100%) rename regression/{exceptions => cbmc-java}/exceptions6/C.class (100%) rename regression/{exceptions => cbmc-java}/exceptions6/D.class (100%) rename regression/{exceptions => cbmc-java}/exceptions6/test.class (100%) rename regression/{exceptions => cbmc-java}/exceptions6/test.desc (100%) rename regression/{exceptions => cbmc-java}/exceptions6/test.java (100%) rename regression/{exceptions/exceptions8 => cbmc-java/exceptions7}/A.class (100%) rename regression/{exceptions/exceptions8 => cbmc-java/exceptions7}/B.class (100%) rename regression/{exceptions/exceptions8 => cbmc-java/exceptions7}/C.class (100%) rename regression/{exceptions => cbmc-java}/exceptions7/test.class (100%) rename regression/{exceptions => cbmc-java}/exceptions7/test.desc (100%) rename regression/{exceptions => cbmc-java}/exceptions7/test.java (100%) create mode 100644 regression/cbmc-java/exceptions8/A.class create mode 100644 regression/cbmc-java/exceptions8/B.class rename regression/{exceptions/exceptions9 => cbmc-java/exceptions8}/C.class (100%) rename regression/{exceptions => cbmc-java}/exceptions8/test.class (100%) rename regression/{exceptions => cbmc-java}/exceptions8/test.desc (100%) rename regression/{exceptions => cbmc-java}/exceptions8/test.java (100%) rename regression/{exceptions => cbmc-java}/exceptions9/A.class (100%) rename regression/{exceptions => cbmc-java}/exceptions9/B.class (100%) create mode 100644 regression/cbmc-java/exceptions9/C.class rename regression/{exceptions => cbmc-java}/exceptions9/test.class (100%) rename regression/{exceptions => cbmc-java}/exceptions9/test.desc (100%) rename regression/{exceptions => cbmc-java}/exceptions9/test.java (100%) delete mode 100644 regression/exceptions/Makefile diff --git a/regression/cbmc-java/NullPointer3/NullPointer3.class b/regression/cbmc-java/NullPointer3/NullPointer3.class index 8ad089310c3a7896b660934861b104537c1edd65..b79f5adef44f30757862ddef9c91c22f2700cf2a 100644 GIT binary patch delta 224 zcmeBU`oko8>ff$?3=9k=3?f_%%nX9;3_|P-!V^Wcw1s@~lM{2o5{ohulX6l+Km;QL zOG!p%F(U(?k6&p{PC$NUUP)?^vGqh-C25w#qI95)aI{ZWVp*boPGVlVesD=qW?s7W z#Ms0VeFjD#WME*`+RnhZ5y)U-Uff$?3=9k=4E$US%nUs247}_Nd=o{rCgvziTp1rA%fJYP3=FJV+Zh-) r0vU`9>_CzYEXc^f$-n``j6gmEgA|YkDP>~ZkEV_lD9#0vVc-S;HuwxN diff --git a/regression/cbmc-java/NullPointer3/NullPointer3.java b/regression/cbmc-java/NullPointer3/NullPointer3.java index 00004f14467..fa8b227dd94 100644 --- a/regression/cbmc-java/NullPointer3/NullPointer3.java +++ b/regression/cbmc-java/NullPointer3/NullPointer3.java @@ -4,5 +4,4 @@ public static void main(String[] args) { throw null; // NULL pointer dereference } - } diff --git a/regression/cbmc-java/NullPointer3/test.desc b/regression/cbmc-java/NullPointer3/test.desc index cc33c21738b..5dd14d8dfb9 100644 --- a/regression/cbmc-java/NullPointer3/test.desc +++ b/regression/cbmc-java/NullPointer3/test.desc @@ -1,9 +1,9 @@ CORE NullPointer3.class ---pointer-check --stop-on-fail +--pointer-check ^EXIT=10$ ^SIGNAL=0$ -^ file NullPointer3.java line 5 function java::NullPointer3.main:\(\[Ljava/lang/String;\)V bytecode_index 1$ +^.*Throw null: FAILURE$ ^VERIFICATION FAILED$ -- ^warning: ignoring diff --git a/regression/exceptions/exceptions1/A.class b/regression/cbmc-java/exceptions1/A.class similarity index 100% rename from regression/exceptions/exceptions1/A.class rename to regression/cbmc-java/exceptions1/A.class diff --git a/regression/exceptions/exceptions1/B.class b/regression/cbmc-java/exceptions1/B.class similarity index 100% rename from regression/exceptions/exceptions1/B.class rename to regression/cbmc-java/exceptions1/B.class diff --git a/regression/exceptions/exceptions1/C.class b/regression/cbmc-java/exceptions1/C.class similarity index 100% rename from regression/exceptions/exceptions1/C.class rename to regression/cbmc-java/exceptions1/C.class diff --git a/regression/exceptions/exceptions1/D.class b/regression/cbmc-java/exceptions1/D.class similarity index 100% rename from regression/exceptions/exceptions1/D.class rename to regression/cbmc-java/exceptions1/D.class diff --git a/regression/exceptions/exceptions1/test.class b/regression/cbmc-java/exceptions1/test.class similarity index 100% rename from regression/exceptions/exceptions1/test.class rename to regression/cbmc-java/exceptions1/test.class diff --git a/regression/exceptions/exceptions1/test.desc b/regression/cbmc-java/exceptions1/test.desc similarity index 80% rename from regression/exceptions/exceptions1/test.desc rename to regression/cbmc-java/exceptions1/test.desc index 7c6146907d0..ca52107829c 100644 --- a/regression/exceptions/exceptions1/test.desc +++ b/regression/cbmc-java/exceptions1/test.desc @@ -4,7 +4,7 @@ test.class ^EXIT=10$ ^SIGNAL=0$ ^.*assertion at file test.java line 26 function.*: FAILURE$ -\*\* 1 of 4 failed (2 iterations)$ +\*\* 1 of 9 failed (2 iterations)$ ^VERIFICATION FAILED$ -- ^warning: ignoring diff --git a/regression/exceptions/exceptions1/test.java b/regression/cbmc-java/exceptions1/test.java similarity index 100% rename from regression/exceptions/exceptions1/test.java rename to regression/cbmc-java/exceptions1/test.java diff --git a/regression/exceptions/exceptions10/A.class b/regression/cbmc-java/exceptions10/A.class similarity index 100% rename from regression/exceptions/exceptions10/A.class rename to regression/cbmc-java/exceptions10/A.class diff --git a/regression/exceptions/exceptions10/B.class b/regression/cbmc-java/exceptions10/B.class similarity index 100% rename from regression/exceptions/exceptions10/B.class rename to regression/cbmc-java/exceptions10/B.class diff --git a/regression/exceptions/exceptions10/C.class b/regression/cbmc-java/exceptions10/C.class similarity index 100% rename from regression/exceptions/exceptions10/C.class rename to regression/cbmc-java/exceptions10/C.class diff --git a/regression/exceptions/exceptions10/test.class b/regression/cbmc-java/exceptions10/test.class similarity index 100% rename from regression/exceptions/exceptions10/test.class rename to regression/cbmc-java/exceptions10/test.class diff --git a/regression/exceptions/exceptions10/test.desc b/regression/cbmc-java/exceptions10/test.desc similarity index 100% rename from regression/exceptions/exceptions10/test.desc rename to regression/cbmc-java/exceptions10/test.desc diff --git a/regression/exceptions/exceptions10/test.java b/regression/cbmc-java/exceptions10/test.java similarity index 100% rename from regression/exceptions/exceptions10/test.java rename to regression/cbmc-java/exceptions10/test.java diff --git a/regression/exceptions/exceptions11/A.class b/regression/cbmc-java/exceptions11/A.class similarity index 100% rename from regression/exceptions/exceptions11/A.class rename to regression/cbmc-java/exceptions11/A.class diff --git a/regression/exceptions/exceptions11/B.class b/regression/cbmc-java/exceptions11/B.class similarity index 100% rename from regression/exceptions/exceptions11/B.class rename to regression/cbmc-java/exceptions11/B.class diff --git a/regression/exceptions/exceptions11/test.class b/regression/cbmc-java/exceptions11/test.class similarity index 100% rename from regression/exceptions/exceptions11/test.class rename to regression/cbmc-java/exceptions11/test.class diff --git a/regression/exceptions/exceptions11/test.desc b/regression/cbmc-java/exceptions11/test.desc similarity index 100% rename from regression/exceptions/exceptions11/test.desc rename to regression/cbmc-java/exceptions11/test.desc diff --git a/regression/exceptions/exceptions11/test.java b/regression/cbmc-java/exceptions11/test.java similarity index 100% rename from regression/exceptions/exceptions11/test.java rename to regression/cbmc-java/exceptions11/test.java diff --git a/regression/exceptions/exceptions12/A.class b/regression/cbmc-java/exceptions12/A.class similarity index 100% rename from regression/exceptions/exceptions12/A.class rename to regression/cbmc-java/exceptions12/A.class diff --git a/regression/exceptions/exceptions12/B.class b/regression/cbmc-java/exceptions12/B.class similarity index 100% rename from regression/exceptions/exceptions12/B.class rename to regression/cbmc-java/exceptions12/B.class diff --git a/regression/exceptions/exceptions12/C.class b/regression/cbmc-java/exceptions12/C.class similarity index 100% rename from regression/exceptions/exceptions12/C.class rename to regression/cbmc-java/exceptions12/C.class diff --git a/regression/exceptions/exceptions12/F.class b/regression/cbmc-java/exceptions12/F.class similarity index 100% rename from regression/exceptions/exceptions12/F.class rename to regression/cbmc-java/exceptions12/F.class diff --git a/regression/exceptions/exceptions12/test.class b/regression/cbmc-java/exceptions12/test.class similarity index 100% rename from regression/exceptions/exceptions12/test.class rename to regression/cbmc-java/exceptions12/test.class diff --git a/regression/exceptions/exceptions12/test.desc b/regression/cbmc-java/exceptions12/test.desc similarity index 100% rename from regression/exceptions/exceptions12/test.desc rename to regression/cbmc-java/exceptions12/test.desc diff --git a/regression/exceptions/exceptions12/test.java b/regression/cbmc-java/exceptions12/test.java similarity index 100% rename from regression/exceptions/exceptions12/test.java rename to regression/cbmc-java/exceptions12/test.java diff --git a/regression/exceptions/exceptions13/A.class b/regression/cbmc-java/exceptions13/A.class similarity index 100% rename from regression/exceptions/exceptions13/A.class rename to regression/cbmc-java/exceptions13/A.class diff --git a/regression/exceptions/exceptions13/B.class b/regression/cbmc-java/exceptions13/B.class similarity index 100% rename from regression/exceptions/exceptions13/B.class rename to regression/cbmc-java/exceptions13/B.class diff --git a/regression/exceptions/exceptions13/C.class b/regression/cbmc-java/exceptions13/C.class similarity index 100% rename from regression/exceptions/exceptions13/C.class rename to regression/cbmc-java/exceptions13/C.class diff --git a/regression/exceptions/exceptions13/F.class b/regression/cbmc-java/exceptions13/F.class similarity index 100% rename from regression/exceptions/exceptions13/F.class rename to regression/cbmc-java/exceptions13/F.class diff --git a/regression/exceptions/exceptions13/test.class b/regression/cbmc-java/exceptions13/test.class similarity index 100% rename from regression/exceptions/exceptions13/test.class rename to regression/cbmc-java/exceptions13/test.class diff --git a/regression/exceptions/exceptions13/test.desc b/regression/cbmc-java/exceptions13/test.desc similarity index 100% rename from regression/exceptions/exceptions13/test.desc rename to regression/cbmc-java/exceptions13/test.desc diff --git a/regression/exceptions/exceptions13/test.java b/regression/cbmc-java/exceptions13/test.java similarity index 100% rename from regression/exceptions/exceptions13/test.java rename to regression/cbmc-java/exceptions13/test.java diff --git a/regression/exceptions/exceptions14/A.class b/regression/cbmc-java/exceptions14/A.class similarity index 100% rename from regression/exceptions/exceptions14/A.class rename to regression/cbmc-java/exceptions14/A.class diff --git a/regression/exceptions/exceptions14/B.class b/regression/cbmc-java/exceptions14/B.class similarity index 100% rename from regression/exceptions/exceptions14/B.class rename to regression/cbmc-java/exceptions14/B.class diff --git a/regression/exceptions/exceptions14/C.class b/regression/cbmc-java/exceptions14/C.class similarity index 100% rename from regression/exceptions/exceptions14/C.class rename to regression/cbmc-java/exceptions14/C.class diff --git a/regression/exceptions/exceptions14/test.class b/regression/cbmc-java/exceptions14/test.class similarity index 100% rename from regression/exceptions/exceptions14/test.class rename to regression/cbmc-java/exceptions14/test.class diff --git a/regression/exceptions/exceptions14/test.desc b/regression/cbmc-java/exceptions14/test.desc similarity index 100% rename from regression/exceptions/exceptions14/test.desc rename to regression/cbmc-java/exceptions14/test.desc diff --git a/regression/exceptions/exceptions14/test.java b/regression/cbmc-java/exceptions14/test.java similarity index 100% rename from regression/exceptions/exceptions14/test.java rename to regression/cbmc-java/exceptions14/test.java diff --git a/regression/exceptions/exceptions15/InetAddress.class b/regression/cbmc-java/exceptions15/InetAddress.class similarity index 100% rename from regression/exceptions/exceptions15/InetAddress.class rename to regression/cbmc-java/exceptions15/InetAddress.class diff --git a/regression/exceptions/exceptions15/InetSocketAddress.class b/regression/cbmc-java/exceptions15/InetSocketAddress.class similarity index 100% rename from regression/exceptions/exceptions15/InetSocketAddress.class rename to regression/cbmc-java/exceptions15/InetSocketAddress.class diff --git a/regression/exceptions/exceptions15/test.class b/regression/cbmc-java/exceptions15/test.class similarity index 100% rename from regression/exceptions/exceptions15/test.class rename to regression/cbmc-java/exceptions15/test.class diff --git a/regression/exceptions/exceptions15/test.desc b/regression/cbmc-java/exceptions15/test.desc similarity index 100% rename from regression/exceptions/exceptions15/test.desc rename to regression/cbmc-java/exceptions15/test.desc diff --git a/regression/exceptions/exceptions15/test.java b/regression/cbmc-java/exceptions15/test.java similarity index 100% rename from regression/exceptions/exceptions15/test.java rename to regression/cbmc-java/exceptions15/test.java diff --git a/regression/exceptions/exceptions7/A.class b/regression/cbmc-java/exceptions16/A.class similarity index 100% rename from regression/exceptions/exceptions7/A.class rename to regression/cbmc-java/exceptions16/A.class diff --git a/regression/exceptions/exceptions2/B.class b/regression/cbmc-java/exceptions16/B.class similarity index 100% rename from regression/exceptions/exceptions2/B.class rename to regression/cbmc-java/exceptions16/B.class diff --git a/regression/exceptions/exceptions2/C.class b/regression/cbmc-java/exceptions16/C.class similarity index 100% rename from regression/exceptions/exceptions2/C.class rename to regression/cbmc-java/exceptions16/C.class diff --git a/regression/cbmc-java/exceptions16/test.class b/regression/cbmc-java/exceptions16/test.class new file mode 100644 index 0000000000000000000000000000000000000000..189317658cea5cab3e52e378ccf0809e28a7198b GIT binary patch literal 718 zcmZWl-A)rh7(KJQ-D#JllpL{WOy5=F+pcO~F+XCaec^JKW z5q>CWH~=*Zl-Hwpq{Z7!hH0d>wCP+is}Ty$=DyobxbiU;~J(}F`qvZZPB+sL7Z^k zUtk|&>>SSPGn6jQ;nK^Cf6AxD7n?0C5;b{TYBEh1NNyU~Z0S<9q~d8dYEs55>R4rK zBWR8Y$q8m~okC`ds8NV);|6XLaf{c7vn6r6`dp$}C9A<*%3dq5z+}Dr4V7a^=LC-Z V754x08=?{{|B2bs9VQm$egkzSbi@Dv literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/exceptions16/test.desc b/regression/cbmc-java/exceptions16/test.desc new file mode 100644 index 00000000000..960b995f7d3 --- /dev/null +++ b/regression/cbmc-java/exceptions16/test.desc @@ -0,0 +1,9 @@ +CORE +test.class +--function test.foo +^EXIT=10$ +^SIGNAL=0$ +^.*assertion at file test.java line 18 function.*: FAILURE$ +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/cbmc-java/exceptions16/test.java b/regression/cbmc-java/exceptions16/test.java new file mode 100644 index 00000000000..9d1c2729516 --- /dev/null +++ b/regression/cbmc-java/exceptions16/test.java @@ -0,0 +1,21 @@ +class A extends RuntimeException {} +class B extends A {} +class C extends B {} + +public class test { + static void foo (int x) { + try { + x++; + } + catch(A exc) { + assert false; + } + + try { + throw new B(); + } + catch(B exc) { + assert false; + } + } +} diff --git a/regression/exceptions/exceptions2/A.class b/regression/cbmc-java/exceptions2/A.class similarity index 100% rename from regression/exceptions/exceptions2/A.class rename to regression/cbmc-java/exceptions2/A.class diff --git a/regression/exceptions/exceptions3/B.class b/regression/cbmc-java/exceptions2/B.class similarity index 100% rename from regression/exceptions/exceptions3/B.class rename to regression/cbmc-java/exceptions2/B.class diff --git a/regression/exceptions/exceptions3/C.class b/regression/cbmc-java/exceptions2/C.class similarity index 100% rename from regression/exceptions/exceptions3/C.class rename to regression/cbmc-java/exceptions2/C.class diff --git a/regression/exceptions/exceptions2/test.class b/regression/cbmc-java/exceptions2/test.class similarity index 100% rename from regression/exceptions/exceptions2/test.class rename to regression/cbmc-java/exceptions2/test.class diff --git a/regression/exceptions/exceptions2/test.desc b/regression/cbmc-java/exceptions2/test.desc similarity index 79% rename from regression/exceptions/exceptions2/test.desc rename to regression/cbmc-java/exceptions2/test.desc index 179b234c875..45f5bac3bc2 100644 --- a/regression/exceptions/exceptions2/test.desc +++ b/regression/cbmc-java/exceptions2/test.desc @@ -4,7 +4,7 @@ test.class ^EXIT=10$ ^SIGNAL=0$ ^.*assertion at file test.java line 15 function.*: FAILURE$ -^\*\* 1 of 2 failed (2 iterations)$ +^\*\* 1 of 5 failed (2 iterations)$ ^VERIFICATION FAILED$ -- ^warning: ignoring diff --git a/regression/exceptions/exceptions2/test.java b/regression/cbmc-java/exceptions2/test.java similarity index 100% rename from regression/exceptions/exceptions2/test.java rename to regression/cbmc-java/exceptions2/test.java diff --git a/regression/exceptions/exceptions3/A.class b/regression/cbmc-java/exceptions3/A.class similarity index 100% rename from regression/exceptions/exceptions3/A.class rename to regression/cbmc-java/exceptions3/A.class diff --git a/regression/exceptions/exceptions4/B.class b/regression/cbmc-java/exceptions3/B.class similarity index 100% rename from regression/exceptions/exceptions4/B.class rename to regression/cbmc-java/exceptions3/B.class diff --git a/regression/exceptions/exceptions4/C.class b/regression/cbmc-java/exceptions3/C.class similarity index 100% rename from regression/exceptions/exceptions4/C.class rename to regression/cbmc-java/exceptions3/C.class diff --git a/regression/exceptions/exceptions3/test.class b/regression/cbmc-java/exceptions3/test.class similarity index 100% rename from regression/exceptions/exceptions3/test.class rename to regression/cbmc-java/exceptions3/test.class diff --git a/regression/exceptions/exceptions3/test.desc b/regression/cbmc-java/exceptions3/test.desc similarity index 100% rename from regression/exceptions/exceptions3/test.desc rename to regression/cbmc-java/exceptions3/test.desc diff --git a/regression/exceptions/exceptions3/test.java b/regression/cbmc-java/exceptions3/test.java similarity index 100% rename from regression/exceptions/exceptions3/test.java rename to regression/cbmc-java/exceptions3/test.java diff --git a/regression/exceptions/exceptions4/A.class b/regression/cbmc-java/exceptions4/A.class similarity index 100% rename from regression/exceptions/exceptions4/A.class rename to regression/cbmc-java/exceptions4/A.class diff --git a/regression/exceptions/exceptions5/B.class b/regression/cbmc-java/exceptions4/B.class similarity index 100% rename from regression/exceptions/exceptions5/B.class rename to regression/cbmc-java/exceptions4/B.class diff --git a/regression/exceptions/exceptions5/C.class b/regression/cbmc-java/exceptions4/C.class similarity index 100% rename from regression/exceptions/exceptions5/C.class rename to regression/cbmc-java/exceptions4/C.class diff --git a/regression/exceptions/exceptions4/test.class b/regression/cbmc-java/exceptions4/test.class similarity index 100% rename from regression/exceptions/exceptions4/test.class rename to regression/cbmc-java/exceptions4/test.class diff --git a/regression/exceptions/exceptions4/test.desc b/regression/cbmc-java/exceptions4/test.desc similarity index 100% rename from regression/exceptions/exceptions4/test.desc rename to regression/cbmc-java/exceptions4/test.desc diff --git a/regression/exceptions/exceptions4/test.java b/regression/cbmc-java/exceptions4/test.java similarity index 100% rename from regression/exceptions/exceptions4/test.java rename to regression/cbmc-java/exceptions4/test.java diff --git a/regression/exceptions/exceptions5/A.class b/regression/cbmc-java/exceptions5/A.class similarity index 100% rename from regression/exceptions/exceptions5/A.class rename to regression/cbmc-java/exceptions5/A.class diff --git a/regression/exceptions/exceptions7/B.class b/regression/cbmc-java/exceptions5/B.class similarity index 100% rename from regression/exceptions/exceptions7/B.class rename to regression/cbmc-java/exceptions5/B.class diff --git a/regression/exceptions/exceptions7/C.class b/regression/cbmc-java/exceptions5/C.class similarity index 100% rename from regression/exceptions/exceptions7/C.class rename to regression/cbmc-java/exceptions5/C.class diff --git a/regression/exceptions/exceptions5/D.class b/regression/cbmc-java/exceptions5/D.class similarity index 100% rename from regression/exceptions/exceptions5/D.class rename to regression/cbmc-java/exceptions5/D.class diff --git a/regression/exceptions/exceptions5/test.class b/regression/cbmc-java/exceptions5/test.class similarity index 100% rename from regression/exceptions/exceptions5/test.class rename to regression/cbmc-java/exceptions5/test.class diff --git a/regression/exceptions/exceptions5/test.desc b/regression/cbmc-java/exceptions5/test.desc similarity index 100% rename from regression/exceptions/exceptions5/test.desc rename to regression/cbmc-java/exceptions5/test.desc diff --git a/regression/exceptions/exceptions5/test.java b/regression/cbmc-java/exceptions5/test.java similarity index 100% rename from regression/exceptions/exceptions5/test.java rename to regression/cbmc-java/exceptions5/test.java diff --git a/regression/exceptions/exceptions6/A.class b/regression/cbmc-java/exceptions6/A.class similarity index 100% rename from regression/exceptions/exceptions6/A.class rename to regression/cbmc-java/exceptions6/A.class diff --git a/regression/exceptions/exceptions6/B.class b/regression/cbmc-java/exceptions6/B.class similarity index 100% rename from regression/exceptions/exceptions6/B.class rename to regression/cbmc-java/exceptions6/B.class diff --git a/regression/exceptions/exceptions6/C.class b/regression/cbmc-java/exceptions6/C.class similarity index 100% rename from regression/exceptions/exceptions6/C.class rename to regression/cbmc-java/exceptions6/C.class diff --git a/regression/exceptions/exceptions6/D.class b/regression/cbmc-java/exceptions6/D.class similarity index 100% rename from regression/exceptions/exceptions6/D.class rename to regression/cbmc-java/exceptions6/D.class diff --git a/regression/exceptions/exceptions6/test.class b/regression/cbmc-java/exceptions6/test.class similarity index 100% rename from regression/exceptions/exceptions6/test.class rename to regression/cbmc-java/exceptions6/test.class diff --git a/regression/exceptions/exceptions6/test.desc b/regression/cbmc-java/exceptions6/test.desc similarity index 100% rename from regression/exceptions/exceptions6/test.desc rename to regression/cbmc-java/exceptions6/test.desc diff --git a/regression/exceptions/exceptions6/test.java b/regression/cbmc-java/exceptions6/test.java similarity index 100% rename from regression/exceptions/exceptions6/test.java rename to regression/cbmc-java/exceptions6/test.java diff --git a/regression/exceptions/exceptions8/A.class b/regression/cbmc-java/exceptions7/A.class similarity index 100% rename from regression/exceptions/exceptions8/A.class rename to regression/cbmc-java/exceptions7/A.class diff --git a/regression/exceptions/exceptions8/B.class b/regression/cbmc-java/exceptions7/B.class similarity index 100% rename from regression/exceptions/exceptions8/B.class rename to regression/cbmc-java/exceptions7/B.class diff --git a/regression/exceptions/exceptions8/C.class b/regression/cbmc-java/exceptions7/C.class similarity index 100% rename from regression/exceptions/exceptions8/C.class rename to regression/cbmc-java/exceptions7/C.class diff --git a/regression/exceptions/exceptions7/test.class b/regression/cbmc-java/exceptions7/test.class similarity index 100% rename from regression/exceptions/exceptions7/test.class rename to regression/cbmc-java/exceptions7/test.class diff --git a/regression/exceptions/exceptions7/test.desc b/regression/cbmc-java/exceptions7/test.desc similarity index 100% rename from regression/exceptions/exceptions7/test.desc rename to regression/cbmc-java/exceptions7/test.desc diff --git a/regression/exceptions/exceptions7/test.java b/regression/cbmc-java/exceptions7/test.java similarity index 100% rename from regression/exceptions/exceptions7/test.java rename to regression/cbmc-java/exceptions7/test.java diff --git a/regression/cbmc-java/exceptions8/A.class b/regression/cbmc-java/exceptions8/A.class new file mode 100644 index 0000000000000000000000000000000000000000..963ae156be051ca07ea2d602053e012a3d27a7a4 GIT binary patch literal 241 zcmXX=O;5r=5PbuswY3W2=*gpUuorF+lg8kw;Q*%hZQaP2c5B)#@o#xD@!${OM-gX{ zNoL+h-b?0i{P_hi$0WiKR{^dAj0ygd4ckY;@a{e*cu&o%CX6#SdfnHBZeLVUi8IZb zQdPNX+3BSuQG(CW@UysN#6;bBCelyKv8QYrJ6YoqP1btzNpmRpEZ_t;J0Rp-H$s}9|kN*P*5s4yPo>K82_(?21 literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/exceptions8/B.class b/regression/cbmc-java/exceptions8/B.class new file mode 100644 index 0000000000000000000000000000000000000000..47ae8f218e49b4ac942425d72a88b21c2772b518 GIT binary patch literal 216 zcmXX7D1o9M#q%+AiT z@6YoEV1a=P9X%U;8$Q8WsZ3RCf!TDLcb3PedAtLN)W> zG^(>I`7{ic1ox2FMIv{qi93}ntJy`|ga-pAfda+`BWV1+DPr)3*K{pl# WT<*@-G|^!l`~vXc^F-)=Q^5xrb|N Date: Fri, 17 Feb 2017 08:42:35 +0000 Subject: [PATCH 106/699] Escaping brackets in test descriptions --- regression/cbmc-java/exceptions1/test.desc | 2 +- regression/cbmc-java/exceptions2/test.desc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/regression/cbmc-java/exceptions1/test.desc b/regression/cbmc-java/exceptions1/test.desc index ca52107829c..638351f4397 100644 --- a/regression/cbmc-java/exceptions1/test.desc +++ b/regression/cbmc-java/exceptions1/test.desc @@ -4,7 +4,7 @@ test.class ^EXIT=10$ ^SIGNAL=0$ ^.*assertion at file test.java line 26 function.*: FAILURE$ -\*\* 1 of 9 failed (2 iterations)$ +\*\* 1 of 9 failed \(2 iterations\)$ ^VERIFICATION FAILED$ -- ^warning: ignoring diff --git a/regression/cbmc-java/exceptions2/test.desc b/regression/cbmc-java/exceptions2/test.desc index 45f5bac3bc2..8645e5ea074 100644 --- a/regression/cbmc-java/exceptions2/test.desc +++ b/regression/cbmc-java/exceptions2/test.desc @@ -4,7 +4,7 @@ test.class ^EXIT=10$ ^SIGNAL=0$ ^.*assertion at file test.java line 15 function.*: FAILURE$ -^\*\* 1 of 5 failed (2 iterations)$ +^\*\* 1 of 5 failed \(2 iterations\)$ ^VERIFICATION FAILED$ -- ^warning: ignoring From 50dfffb70edce4c47ea6a35dfe26b43588011a2e Mon Sep 17 00:00:00 2001 From: Cristina Date: Fri, 17 Feb 2017 09:38:26 +0000 Subject: [PATCH 107/699] Fixed test description for cbmc-java/virtual7 The exception handling instrumentation introduces new labels and thus the target of the gotos in the goto-program needs to be incremented. --- regression/cbmc-java/virtual7/test.desc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/regression/cbmc-java/virtual7/test.desc b/regression/cbmc-java/virtual7/test.desc index b2b26ecb9ce..3846f5c4a69 100644 --- a/regression/cbmc-java/virtual7/test.desc +++ b/regression/cbmc-java/virtual7/test.desc @@ -3,10 +3,10 @@ test.class --show-goto-functions ^EXIT=0$ ^SIGNAL=0$ -IF "java::E".*THEN GOTO [12] -IF "java::B".*THEN GOTO [12] -IF "java::D".*THEN GOTO [12] -IF "java::C".*THEN GOTO [12] +IF "java::E".*THEN GOTO [67] +IF "java::B".*THEN GOTO [67] +IF "java::D".*THEN GOTO [67] +IF "java::C".*THEN GOTO [67] -- IF "java::A".*THEN GOTO -GOTO 4 +GOTO 9 From 6f5d6409f3d335102cfc5ec93bbfda07c2d879d3 Mon Sep 17 00:00:00 2001 From: Cristina Date: Tue, 28 Feb 2017 19:34:06 +0000 Subject: [PATCH 108/699] Recompute live ranges for local variables and add corresponding DEAD instructions This needs to be done because the exception handling instrumentation introduces GOTOs which modify the existent live ranges. --- src/goto-programs/remove_exceptions.cpp | 104 +++++++++++++++++++----- 1 file changed, 83 insertions(+), 21 deletions(-) diff --git a/src/goto-programs/remove_exceptions.cpp b/src/goto-programs/remove_exceptions.cpp index 14700921e24..4b4e5debe35 100644 --- a/src/goto-programs/remove_exceptions.cpp +++ b/src/goto-programs/remove_exceptions.cpp @@ -7,11 +7,13 @@ Author: Cristina David Date: December 2016 \*******************************************************************/ -#define DEBUG + #ifdef DEBUG #include #endif + #include +#include #include #include @@ -47,19 +49,20 @@ class remove_exceptionst void instrument_exception_handlers( const goto_functionst::function_mapt::iterator &); - void add_gotos( const goto_functionst::function_mapt::iterator &); void add_throw_gotos( const goto_functionst::function_mapt::iterator &, const goto_programt::instructionst::iterator &, - const stack_catcht &); + const stack_catcht &, + std::vector &); void add_function_call_gotos( const goto_functionst::function_mapt::iterator &, const goto_programt::instructionst::iterator &, - const stack_catcht &); + const stack_catcht &, + std::vector &); }; /*******************************************************************\ @@ -134,7 +137,6 @@ void remove_exceptionst::add_exceptional_returns( rhs_expr_null); t_null->function=function_id; } - return; } /*******************************************************************\ @@ -318,11 +320,13 @@ Purpose: instruments each throw with conditional GOTOS to the void remove_exceptionst::add_throw_gotos( const goto_functionst::function_mapt::iterator &func_it, const goto_programt::instructionst::iterator &instr_it, - const remove_exceptionst::stack_catcht &stack_catch) + const remove_exceptionst::stack_catcht &stack_catch, + std::vector &locals) { assert(instr_it->type==THROW); goto_programt &goto_program=func_it->second.body; + const irep_idt &function_id=func_it->first; assert(instr_it->code.operands().size()==1); @@ -341,6 +345,11 @@ void remove_exceptionst::add_throw_gotos( t_end->function=instr_it->function; } + // find the symbol corresponding to the caught exceptions + const symbolt &exc_symbol= + symbol_table.lookup(id2string(function_id)+EXC_SUFFIX); + symbol_exprt exc_thrown=exc_symbol.symbol_expr(); + // add GOTOs implementing the dynamic dispatch of the // exception handlers for(std::size_t i=stack_catch.size(); i-->0;) @@ -359,15 +368,21 @@ void remove_exceptionst::add_throw_gotos( // use instanceof to check that this is the correct handler symbol_typet type(stack_catch[i][j].first); type_exprt expr(type); - // find the symbol corresponding to the caught exceptions - exprt exc_symbol=instr_it->code; - while(exc_symbol.id()!=ID_symbol) - exc_symbol=exc_symbol.op0(); - binary_predicate_exprt check(exc_symbol, ID_java_instanceof, expr); + binary_predicate_exprt check(exc_thrown, ID_java_instanceof, expr); t_exc->guard=check; } } + + // add dead instructions + for(const auto &local : locals) + { + goto_programt::targett t_dead=goto_program.insert_after(instr_it); + t_dead->make_dead(); + t_dead->code=code_deadt(local); + t_dead->source_location=instr_it->source_location; + t_dead->function=instr_it->function; + } } /*******************************************************************\ @@ -386,7 +401,8 @@ Purpose: instruments each function call that may escape exceptions void remove_exceptionst::add_function_call_gotos( const goto_functionst::function_mapt::iterator &func_it, const goto_programt::instructionst::iterator &instr_it, - const stack_catcht &stack_catch) + const stack_catcht &stack_catch, + std::vector &locals) { assert(instr_it->type==FUNCTION_CALL); @@ -403,7 +419,7 @@ void remove_exceptionst::add_function_call_gotos( if(symbol_table.has_symbol(id2string(callee_id)+EXC_SUFFIX)) { - // dynamic dispatch of the escaped exception + // we may have an escaping exception const symbolt &callee_exc_symbol= symbol_table.lookup(id2string(callee_id)+EXC_SUFFIX); symbol_exprt callee_exc=callee_exc_symbol.symbol_expr(); @@ -429,11 +445,20 @@ void remove_exceptionst::add_function_call_gotos( } } + // add dead instructions + for(const auto &local : locals) + { + goto_programt::targett t_dead=goto_program.insert_after(instr_it); + t_dead->make_dead(); + t_dead->code=code_deadt(local); + t_dead->source_location=instr_it->source_location; + t_dead->function=instr_it->function; + } + // add a null check (so that instanceof can be applied) equal_exprt eq_null( callee_exc, null_pointer_exprt(pointer_typet(empty_typet()))); - // jump to the next instruction goto_programt::targett t_null=goto_program.insert_after(instr_it); t_null->make_goto(next_it); t_null->source_location=instr_it->source_location; @@ -458,20 +483,54 @@ Purpose: instruments each throw and function calls that may escape exceptions void remove_exceptionst::add_gotos( const goto_functionst::function_mapt::iterator &func_it) { - // Stack of try-catch blocks - stack_catcht stack_catch; - + stack_catcht stack_catch; // stack of try-catch blocks + std::vector> stack_locals; // stack of local vars + std::vector locals; + bool skip_dead=false; goto_programt &goto_program=func_it->second.body; if(goto_program.empty()) return; Forall_goto_program_instructions(instr_it, goto_program) { + if(!instr_it->labels.empty()) + skip_dead=false; + if(instr_it->is_decl()) + { + code_declt decl=to_code_decl(instr_it->code); + locals.push_back(decl.symbol()); + } + if(instr_it->is_dead()) + { + code_deadt dead=to_code_dead(instr_it->code); + auto it=std::find(locals.begin(), + locals.end(), + dead.symbol()); + // avoid DEAD re-declarations + if(it==locals.end()) + { + if(skip_dead) + { + // this DEAD has been already added by a throw + instr_it->make_skip(); + } + } + else + { + locals.erase(it); + } + } // it's a CATCH but not a handler - if(instr_it->type==CATCH && !instr_it->code.has_operands()) + else if(instr_it->type==CATCH && !instr_it->code.has_operands()) { if(instr_it->targets.empty()) // pop { + // pop the local vars stack + if(!stack_locals.empty()) + { + locals=stack_locals.back(); + stack_locals.pop_back(); + } // pop from the stack if possible if(!stack_catch.empty()) { @@ -486,6 +545,9 @@ void remove_exceptionst::add_gotos( } else // push { + stack_locals.push_back(locals); + locals.clear(); + remove_exceptionst::catch_handlerst exception; stack_catch.push_back(exception); remove_exceptionst::catch_handlerst &last_exception= @@ -505,16 +567,16 @@ void remove_exceptionst::add_gotos( i++; } } - instr_it->make_skip(); } else if(instr_it->type==THROW) { - add_throw_gotos(func_it, instr_it, stack_catch); + skip_dead=true; + add_throw_gotos(func_it, instr_it, stack_catch, locals); } else if(instr_it->type==FUNCTION_CALL) { - add_function_call_gotos(func_it, instr_it, stack_catch); + add_function_call_gotos(func_it, instr_it, stack_catch, locals); } } } From d0d20360ef4cd04b32dc254c6ccab5f4a101fbdf Mon Sep 17 00:00:00 2001 From: Cristina Date: Tue, 28 Feb 2017 19:35:54 +0000 Subject: [PATCH 109/699] Forced try-catch to start a new basic block This was required in order for variables local to the try-catch to be declared at the right location. This way, after adding the exception instrumentation in remove_exceptions, we will be able to correctly re-compute live ranges for these variables. --- .../java_bytecode_convert_method.cpp | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 44afd69b72a..6b4cec79055 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -2195,7 +2195,10 @@ codet java_bytecode_convert_methodt::convert_instructions( std::vector exception_ids; std::vector handler_labels; - // add the CATCH-PUSH instruction(s) + // for each try-catch add a CATCH-PUSH instruction + // each CATCH-PUSH records a list of all the handler labels + // together with a list of all the exception ids + // be aware of different try-catch blocks with the same starting pc std::size_t pos=0; size_t end_pc=0; @@ -2215,8 +2218,7 @@ codet java_bytecode_convert_methodt::convert_instructions( method.exception_table[pos].end_pc==end_pc) { exception_ids.push_back( - method.exception_table[pos]. - catch_type.get_identifier()); + method.exception_table[pos].catch_type.get_identifier()); // record the exception handler in the CATCH-PUSH // instruction by generating a label corresponding to // the handler's pc @@ -2413,6 +2415,7 @@ codet java_bytecode_convert_methodt::convert_instructions( // First create a simple flat list of basic blocks. We'll add lexical nesting // constructs as variable live-ranges require next. bool start_new_block=true; + int previous_address=-1; for(const auto &address_pair : address_map) { const unsigned address=address_pair.first; @@ -2426,6 +2429,16 @@ codet java_bytecode_convert_methodt::convert_instructions( // (e.g. due to exceptional control flow) if(!start_new_block) start_new_block=address_pair.second.predecessors.size()>1; + // Start a new lexical block if we've just entered a try block + if(!start_new_block && previous_address!=-1) + { + for(const auto &exception_row : method.exception_table) + if(exception_row.start_pc==previous_address) + { + start_new_block=true; + break; + } + } if(start_new_block) { @@ -2445,6 +2458,8 @@ codet java_bytecode_convert_methodt::convert_instructions( add_to_block.add(c); } start_new_block=address_pair.second.successors.size()>1; + + previous_address=address; } // Find out where temporaries are used: From 18fa65d50c84162e55b761c27c1f63c9f509cd98 Mon Sep 17 00:00:00 2001 From: Cristina Date: Thu, 2 Mar 2017 15:46:03 +0000 Subject: [PATCH 110/699] Restructuring such that the exceptions instrumentation is added in one pass over the goto-program --- src/goto-programs/goto_program_template.h | 8 + src/goto-programs/remove_exceptions.cpp | 286 +++++++----------- .../java_bytecode_convert_method.cpp | 21 +- src/util/std_code.h | 4 +- 4 files changed, 124 insertions(+), 195 deletions(-) diff --git a/src/goto-programs/goto_program_template.h b/src/goto-programs/goto_program_template.h index 77161fcb4d8..bd9cb39c73e 100644 --- a/src/goto-programs/goto_program_template.h +++ b/src/goto-programs/goto_program_template.h @@ -474,6 +474,14 @@ class goto_program_templatet instructions.clear(); } + targett get_end_function() + { + assert(!instructions.empty()); + targett end_function=--instructions.end(); + assert(end_function->is_end_function()); + return end_function; + } + //! Copy a full goto program, preserving targets void copy_from(const goto_program_templatet &src); diff --git a/src/goto-programs/remove_exceptions.cpp b/src/goto-programs/remove_exceptions.cpp index 4b4e5debe35..8bbbd79e165 100644 --- a/src/goto-programs/remove_exceptions.cpp +++ b/src/goto-programs/remove_exceptions.cpp @@ -41,28 +41,24 @@ class remove_exceptionst void add_exceptional_returns( const goto_functionst::function_mapt::iterator &); - void replace_throws( - const goto_functionst::function_mapt::iterator &); - - void instrument_function_calls( - const goto_functionst::function_mapt::iterator &); - - void instrument_exception_handlers( - const goto_functionst::function_mapt::iterator &); - void add_gotos( - const goto_functionst::function_mapt::iterator &); + void instrument_exception_handler( + const goto_functionst::function_mapt::iterator &, + const goto_programt::instructionst::iterator &); - void add_throw_gotos( + void instrument_throw( const goto_functionst::function_mapt::iterator &, const goto_programt::instructionst::iterator &, const stack_catcht &, std::vector &); - void add_function_call_gotos( + void instrument_function_call( const goto_functionst::function_mapt::iterator &, const goto_programt::instructionst::iterator &, const stack_catcht &, std::vector &); + + void instrument_exceptions( + const goto_functionst::function_mapt::iterator &); }; /*******************************************************************\ @@ -99,7 +95,7 @@ void remove_exceptionst::add_exceptional_returns( // function calls that may escape exceptions. However, this will // require multiple passes. bool add_exceptional_var=false; - Forall_goto_program_instructions(instr_it, goto_program) + forall_goto_program_instructions(instr_it, goto_program) if(instr_it->is_throw() || instr_it->is_function_call()) { add_exceptional_var=true; @@ -125,8 +121,7 @@ void remove_exceptionst::add_exceptional_returns( // initialize the exceptional return with NULL symbol_exprt lhs_expr_null=new_symbol.symbol_expr(); - exprt rhs_expr_null; - rhs_expr_null=null_pointer_exprt(pointer_typet(empty_typet())); + null_pointer_exprt rhs_expr_null((pointer_typet(empty_typet()))); goto_programt::targett t_null= goto_program.insert_before(goto_program.instructions.begin()); t_null->make_assignment(); @@ -141,106 +136,7 @@ void remove_exceptionst::add_exceptional_returns( /*******************************************************************\ -Function: remove_exceptionst::replace_throws - -Inputs: - -Outputs: - -Purpose: turns 'throw x' in function f into an assignment to f#exc_value - -\*******************************************************************/ - -void remove_exceptionst::replace_throws( - const goto_functionst::function_mapt::iterator &func_it) -{ - const irep_idt &function_id=func_it->first; - goto_programt &goto_program=func_it->second.body; - - if(goto_program.empty()) - return; - - Forall_goto_program_instructions(instr_it, goto_program) - { - if(instr_it->is_throw() && - symbol_table.has_symbol(id2string(function_id)+EXC_SUFFIX)) - { - assert(instr_it->code.operands().size()==1); - const symbolt &exc_symbol= - symbol_table.lookup(id2string(function_id)+EXC_SUFFIX); - - // replace "throw x;" by "f#exception_value=x;" - symbol_exprt lhs_expr=exc_symbol.symbol_expr(); - // find the symbol corresponding to the thrown exceptions - exprt exc_expr=instr_it->code; - while(exc_expr.id()!=ID_symbol && exc_expr.has_operands()) - exc_expr=exc_expr.op0(); - - // add the assignment with the appropriate cast - code_assignt assignment(typecast_exprt(lhs_expr, exc_expr.type()), - exc_expr); - // now turn the `throw' into `assignment' - instr_it->type=ASSIGN; - instr_it->code=assignment; - } - } -} - -/*******************************************************************\ - -Function: remove_exceptionst::instrument_function_calls - -Inputs: - -Outputs: - -Purpose: after each function call g() in function f - adds f#exception_value=g#exception_value; - -\*******************************************************************/ - -void remove_exceptionst::instrument_function_calls( - const goto_functionst::function_mapt::iterator &func_it) -{ - const irep_idt &caller_id=func_it->first; - goto_programt &goto_program=func_it->second.body; - - if(goto_program.empty()) - return; - - Forall_goto_program_instructions(instr_it, goto_program) - { - if(instr_it->is_function_call()) - { - code_function_callt &function_call=to_code_function_call(instr_it->code); - const irep_idt &callee_id= - to_symbol_expr(function_call.function()).get_identifier(); - - // can exceptions escape? - if(symbol_table.has_symbol(id2string(callee_id)+EXC_SUFFIX) && - symbol_table.has_symbol(id2string(caller_id)+EXC_SUFFIX)) - { - const symbolt &callee= - symbol_table.lookup(id2string(callee_id)+EXC_SUFFIX); - const symbolt &caller= - symbol_table.lookup(id2string(caller_id)+EXC_SUFFIX); - - symbol_exprt rhs_expr=callee.symbol_expr(); - symbol_exprt lhs_expr=caller.symbol_expr(); - - goto_programt::targett t=goto_program.insert_after(instr_it); - t->make_assignment(); - t->source_location=instr_it->source_location; - t->code=code_assignt(lhs_expr, rhs_expr); - t->function=instr_it->function; - } - } - } -} - -/*******************************************************************\ - -Function: remove_exceptionst::instrument_exception_handlers +Function: remove_exceptionst::instrument_exception_handler Inputs: @@ -251,62 +147,52 @@ Purpose: at the beginning of each handler in function f \*******************************************************************/ -void remove_exceptionst::instrument_exception_handlers( - const goto_functionst::function_mapt::iterator &func_it) +void remove_exceptionst::instrument_exception_handler( + const goto_functionst::function_mapt::iterator &func_it, + const goto_programt::instructionst::iterator &instr_it) { const irep_idt &function_id=func_it->first; goto_programt &goto_program=func_it->second.body; - if(goto_program.empty()) - return; + assert(instr_it->type==CATCH && instr_it->code.has_operands()); - Forall_goto_program_instructions(instr_it, goto_program) + // retrieve the exception variable + const exprt &exception=instr_it->code.op0(); + + if(symbol_table.has_symbol(id2string(function_id)+EXC_SUFFIX)) { - // is this a handler - if(instr_it->type==CATCH && instr_it->code.has_operands()) - { - // retrieve the exception variable - const irept &exception=instr_it->code.op0(); + const symbolt &function_symbol= + symbol_table.lookup(id2string(function_id)+EXC_SUFFIX); + // next we reset the exceptional return to NULL + symbol_exprt lhs_expr_null=function_symbol.symbol_expr(); + null_pointer_exprt rhs_expr_null((pointer_typet(empty_typet()))); - if(symbol_table.has_symbol(id2string(function_id)+EXC_SUFFIX)) - { - const symbolt &function_symbol= - symbol_table.lookup(id2string(function_id)+EXC_SUFFIX); - // next we reset the exceptional return to NULL - symbol_exprt lhs_expr_null=function_symbol.symbol_expr(); - exprt rhs_expr_null; - rhs_expr_null=null_pointer_exprt(pointer_typet(empty_typet())); - - // add the assignment - goto_programt::targett t_null=goto_program.insert_after(instr_it); - t_null->make_assignment(); - t_null->source_location=instr_it->source_location; - t_null->code=code_assignt( - lhs_expr_null, - rhs_expr_null); - t_null->function=instr_it->function; - - // add the assignment exc=f#exception_value - symbol_exprt rhs_expr_exc=function_symbol.symbol_expr(); - - const exprt &lhs_expr_exc=static_cast(exception); - goto_programt::targett t_exc=goto_program.insert_after(instr_it); - t_exc->make_assignment(); - t_exc->source_location=instr_it->source_location; - t_exc->code=code_assignt( - typecast_exprt(lhs_expr_exc, rhs_expr_exc.type()), - rhs_expr_exc); - t_exc->function=instr_it->function; - } + // add the assignment + goto_programt::targett t_null=goto_program.insert_after(instr_it); + t_null->make_assignment(); + t_null->source_location=instr_it->source_location; + t_null->code=code_assignt( + lhs_expr_null, + rhs_expr_null); + t_null->function=instr_it->function; - instr_it->make_skip(); - } + // add the assignment exc=f#exception_value + symbol_exprt rhs_expr_exc=function_symbol.symbol_expr(); + + goto_programt::targett t_exc=goto_program.insert_after(instr_it); + t_exc->make_assignment(); + t_exc->source_location=instr_it->source_location; + t_exc->code=code_assignt( + typecast_exprt(exception, rhs_expr_exc.type()), + rhs_expr_exc); + t_exc->function=instr_it->function; } + instr_it->make_skip(); } /*******************************************************************\ -Function: remove_exceptionst::add_gotos_throw +Function: remove_exceptionst::instrument_throw Inputs: @@ -317,7 +203,7 @@ Purpose: instruments each throw with conditional GOTOS to the \*******************************************************************/ -void remove_exceptionst::add_throw_gotos( +void remove_exceptionst::instrument_throw( const goto_functionst::function_mapt::iterator &func_it, const goto_programt::instructionst::iterator &instr_it, const remove_exceptionst::stack_catcht &stack_catch, @@ -331,10 +217,7 @@ void remove_exceptionst::add_throw_gotos( assert(instr_it->code.operands().size()==1); // find the end of the function - goto_programt::targett end_function; - for(end_function=instr_it; - !end_function->is_end_function(); - end_function++) {} + goto_programt::targett end_function=goto_program.get_end_function(); if(end_function!=instr_it) { // jump to the end of the function @@ -345,6 +228,7 @@ void remove_exceptionst::add_throw_gotos( t_end->function=instr_it->function; } + // find the symbol corresponding to the caught exceptions const symbolt &exc_symbol= symbol_table.lookup(id2string(function_id)+EXC_SUFFIX); @@ -383,22 +267,34 @@ void remove_exceptionst::add_throw_gotos( t_dead->source_location=instr_it->source_location; t_dead->function=instr_it->function; } + + // replace "throw x;" by "f#exception_value=x;" + exprt exc_expr=instr_it->code; + while(exc_expr.id()!=ID_symbol && exc_expr.has_operands()) + exc_expr=exc_expr.op0(); + + // add the assignment with the appropriate cast + code_assignt assignment(typecast_exprt(exc_thrown, exc_expr.type()), + exc_expr); + // now turn the `throw' into `assignment' + instr_it->type=ASSIGN; + instr_it->code=assignment; } /*******************************************************************\ -Function: remove_exceptionst::add_function_call_gotos +Function: remove_exceptionst::instrument_function_call Inputs: Outputs: Purpose: instruments each function call that may escape exceptions - with conditional GOTOS to the corresponding exception handlers + with conditional GOTOS to the corresponding exception handlers \*******************************************************************/ -void remove_exceptionst::add_function_call_gotos( +void remove_exceptionst::instrument_function_call( const goto_functionst::function_mapt::iterator &func_it, const goto_programt::instructionst::iterator &instr_it, const stack_catcht &stack_catch, @@ -407,6 +303,7 @@ void remove_exceptionst::add_function_call_gotos( assert(instr_it->type==FUNCTION_CALL); goto_programt &goto_program=func_it->second.body; + const irep_idt &function_id=func_it->first; // save the address of the next instruction goto_programt::instructionst::iterator next_it=instr_it; @@ -424,6 +321,18 @@ void remove_exceptionst::add_function_call_gotos( symbol_table.lookup(id2string(callee_id)+EXC_SUFFIX); symbol_exprt callee_exc=callee_exc_symbol.symbol_expr(); + // find the end of the function + goto_programt::targett end_function=goto_program.get_end_function(); + if(end_function!=instr_it) + { + // jump to the end of the function + // this will appear after the GOTO-based dynamic dispatch below + goto_programt::targett t_end=goto_program.insert_after(instr_it); + t_end->make_goto(end_function); + t_end->source_location=instr_it->source_location; + t_end->function=instr_it->function; + } + for(std::size_t i=stack_catch.size(); i-->0;) { for(std::size_t j=stack_catch[i].size(); j-->0;) @@ -464,43 +373,57 @@ void remove_exceptionst::add_function_call_gotos( t_null->source_location=instr_it->source_location; t_null->function=instr_it->function; t_null->guard=eq_null; + + // after each function call g() in function f + // adds f#exception_value=g#exception_value; + const symbolt &caller= + symbol_table.lookup(id2string(function_id)+EXC_SUFFIX); + const symbol_exprt &lhs_expr=caller.symbol_expr(); + + goto_programt::targett t=goto_program.insert_after(instr_it); + t->make_assignment(); + t->source_location=instr_it->source_location; + t->code=code_assignt(lhs_expr, callee_exc); + t->function=instr_it->function; } } /*******************************************************************\ -Function: remove_exceptionst::add_gotos +Function: remove_exceptionst::instrument_exceptions Inputs: Outputs: -Purpose: instruments each throw and function calls that may escape exceptions - with conditional GOTOS to the corresponding exception handlers +Purpose: instruments throws, function calls that may escape exceptions + and exception handlers. Additionally, it re-computes + the live-range of local variables in order to add DEAD instructions. \*******************************************************************/ -void remove_exceptionst::add_gotos( +void remove_exceptionst::instrument_exceptions( const goto_functionst::function_mapt::iterator &func_it) { stack_catcht stack_catch; // stack of try-catch blocks std::vector> stack_locals; // stack of local vars std::vector locals; - bool skip_dead=false; goto_programt &goto_program=func_it->second.body; if(goto_program.empty()) return; Forall_goto_program_instructions(instr_it, goto_program) { + // this flag is used to skip DEAD redeclaration if(!instr_it->labels.empty()) skip_dead=false; + if(instr_it->is_decl()) { code_declt decl=to_code_decl(instr_it->code); locals.push_back(decl.symbol()); } - if(instr_it->is_dead()) + else if(instr_it->is_dead()) { code_deadt dead=to_code_dead(instr_it->code); auto it=std::find(locals.begin(), @@ -569,19 +492,23 @@ void remove_exceptionst::add_gotos( } instr_it->make_skip(); } + // handler + else if(instr_it->type==CATCH && instr_it->code.has_operands()) + { + instrument_exception_handler(func_it, instr_it); + } else if(instr_it->type==THROW) { skip_dead=true; - add_throw_gotos(func_it, instr_it, stack_catch, locals); + instrument_throw(func_it, instr_it, stack_catch, locals); } else if(instr_it->type==FUNCTION_CALL) { - add_function_call_gotos(func_it, instr_it, stack_catch, locals); + instrument_function_call(func_it, instr_it, stack_catch, locals); } } } - /*******************************************************************\ Function: remove_exceptionst::operator() @@ -597,16 +524,9 @@ Function: remove_exceptionst::operator() void remove_exceptionst::operator()(goto_functionst &goto_functions) { Forall_goto_functions(it, goto_functions) - { add_exceptional_returns(it); - } Forall_goto_functions(it, goto_functions) - { - instrument_exception_handlers(it); - add_gotos(it); - instrument_function_calls(it); - replace_throws(it); - } + instrument_exceptions(it); } /*******************************************************************\ diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 6b4cec79055..8e14d5731dc 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -5,6 +5,7 @@ Module: JAVA Bytecode Language Conversion Author: Daniel Kroening, kroening@kroening.com \*******************************************************************/ + #ifdef DEBUG #include #endif @@ -1117,10 +1118,10 @@ codet java_bytecode_convert_methodt::convert_instructions( // we throw away the first statement in an exception handler // as we don't know if a function call had a normal or exceptional return - size_t e; - for(e=0; ehandler_pc) { exprt exc_var=variable( arg0, statement[0], @@ -1137,7 +1138,7 @@ codet java_bytecode_convert_methodt::convert_instructions( catch_handler_expr.get_sub().resize(1); catch_handler_expr.get_sub()[0]=exc_var; - codet catch_handler=code_expressiont(catch_handler_expr); + code_expressiont catch_handler(catch_handler_expr); code_labelt newlabel(label(std::to_string(cur_pc)), code_blockt()); @@ -1151,7 +1152,7 @@ codet java_bytecode_convert_methodt::convert_instructions( } } - if(e Date: Thu, 2 Mar 2017 16:53:29 +0000 Subject: [PATCH 111/699] Add jump to the end of the current function if a function call throws an exception for which there is no handler --- regression/cbmc-java/exceptions9/test.class | Bin 976 -> 976 bytes src/goto-programs/remove_exceptions.cpp | 29 ++------------------ 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/regression/cbmc-java/exceptions9/test.class b/regression/cbmc-java/exceptions9/test.class index 42f38bdf8b411bc40f4fb15444a6d085cda2a375..ee137ed9bf6ccb8312157e118fe6f87aedaec1a9 100644 GIT binary patch delta 25 gcmcb>et~_13p1}OgCK)4gAjuXg9d}zet~_13p1}8gCK(ngAju%g9d~8labels.empty()) - skip_dead=false; - if(instr_it->is_decl()) { code_declt decl=to_code_decl(instr_it->code); locals.push_back(decl.symbol()); } - else if(instr_it->is_dead()) - { - code_deadt dead=to_code_dead(instr_it->code); - auto it=std::find(locals.begin(), - locals.end(), - dead.symbol()); - // avoid DEAD re-declarations - if(it==locals.end()) - { - if(skip_dead) - { - // this DEAD has been already added by a throw - instr_it->make_skip(); - } - } - else - { - locals.erase(it); - } - } - // it's a CATCH but not a handler + // it's a CATCH but not a handler (as it has no operands) else if(instr_it->type==CATCH && !instr_it->code.has_operands()) { if(instr_it->targets.empty()) // pop @@ -492,14 +468,13 @@ void remove_exceptionst::instrument_exceptions( } instr_it->make_skip(); } - // handler + // CATCH handler else if(instr_it->type==CATCH && instr_it->code.has_operands()) { instrument_exception_handler(func_it, instr_it); } else if(instr_it->type==THROW) { - skip_dead=true; instrument_throw(func_it, instr_it, stack_catch, locals); } else if(instr_it->type==FUNCTION_CALL) From 8d2a26b86b1ecc3b4d3b16b98a229000a988d07f Mon Sep 17 00:00:00 2001 From: Cristina Date: Thu, 2 Mar 2017 16:59:39 +0000 Subject: [PATCH 112/699] Modified the expected goto-program for cbmc-java/virtual7 as exception handling instrumentation introduces new labels and GOTOs --- regression/cbmc-java/virtual7/test.desc | 1 - 1 file changed, 1 deletion(-) diff --git a/regression/cbmc-java/virtual7/test.desc b/regression/cbmc-java/virtual7/test.desc index 3846f5c4a69..2e196d82e8c 100644 --- a/regression/cbmc-java/virtual7/test.desc +++ b/regression/cbmc-java/virtual7/test.desc @@ -9,4 +9,3 @@ IF "java::D".*THEN GOTO [67] IF "java::C".*THEN GOTO [67] -- IF "java::A".*THEN GOTO -GOTO 9 From 28d00ebd17309691e57064248477df8b8e1e3dc0 Mon Sep 17 00:00:00 2001 From: Cristina Date: Thu, 2 Mar 2017 17:13:47 +0000 Subject: [PATCH 113/699] + regression test for Java exception handling --- regression/cbmc-java/exceptions18/A.class | Bin 0 -> 241 bytes regression/cbmc-java/exceptions18/Test.class | Bin 0 -> 756 bytes regression/cbmc-java/exceptions18/Test.java | 23 +++++++++++++++++++ regression/cbmc-java/exceptions18/test.desc | 8 +++++++ 4 files changed, 31 insertions(+) create mode 100644 regression/cbmc-java/exceptions18/A.class create mode 100644 regression/cbmc-java/exceptions18/Test.class create mode 100644 regression/cbmc-java/exceptions18/Test.java create mode 100644 regression/cbmc-java/exceptions18/test.desc diff --git a/regression/cbmc-java/exceptions18/A.class b/regression/cbmc-java/exceptions18/A.class new file mode 100644 index 0000000000000000000000000000000000000000..eb37079f4ed73d57cc2b6947f9e46c6bcc1e8e5b GIT binary patch literal 241 zcmXX=Jxjzu5Pg$RlZ!?ytt{2z(%30N5Uqm6T}Z!)i|&!^9?3@hTULUFKfoU)&PE4j z-Usi&eE)oY0l30(3Ll3tj$-75=tgN}ZwdbSMMDVg%#$SKmD2KY9$GopqV3r^sZ1yO zMvThoe>1QzYT{~DUK7%-na55(C>Kv^Iob72yow9~LIRb9Q>Tkw=;vZHYpVu%|JKR9 tRYv0s9>3*=c)7wDF)J9I6JCCR-kEra`9_OLIAEUr1&|=)<>EFAy< literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/exceptions18/Test.class b/regression/cbmc-java/exceptions18/Test.class new file mode 100644 index 0000000000000000000000000000000000000000..1c2f3dba0083acf483f5b48a1fc3425e77f16268 GIT binary patch literal 756 zcmX|7O-~b16g_w5&Ac)cD71peSBs#fel!v60+j?zNH7%_5E2s;GOZ&H){ZGtqptfq z+_GjPi6(aMPjZ2t_gY=N`*H5Q=e&D=U48!vU<0cGd=xcG0UQ(qcv#lBsj(vPAII%D z-4eLvwIhLgn!Jt#6ZNR6n0{h4?&f_jnBwYKa9@ON8~t3 z5`jm195SnK8|;n2RC&+P%NM>qfew%3c01}Y`@~0nB1t#3$Y*Aaf7#eU8aCfO4?kE* z`|FY*I7qskX0#iduZ`={Z@Fbjnm=*?_?u z9#$x0S*8b_LzWD)3FIvEB&G&@QX#52Rdb*898p_6SKOMK`-;3<^M)Fme&rifPsuq( zHx)Z(RsS6R{=NPMrvt3uHoe2e9?-gWn`cx2e{VEBs%lIU&l4#ynx>t>0 Date: Sat, 4 Mar 2017 12:00:51 +0100 Subject: [PATCH 114/699] allow regex to limit class files loaded from JAR --- src/cbmc/cbmc_parse_options.cpp | 1 + src/cbmc/cbmc_parse_options.h | 1 + src/java_bytecode/jar_file.cpp | 23 ++++++++++++------ src/java_bytecode/jar_file.h | 25 +++++++++++++------- src/java_bytecode/java_bytecode_language.cpp | 5 ++++ src/java_bytecode/java_bytecode_language.h | 1 + src/java_bytecode/java_class_loader.h | 4 ++++ 7 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/cbmc/cbmc_parse_options.cpp b/src/cbmc/cbmc_parse_options.cpp index 6eb044257c6..069034fa7a6 100644 --- a/src/cbmc/cbmc_parse_options.cpp +++ b/src/cbmc/cbmc_parse_options.cpp @@ -1158,6 +1158,7 @@ void cbmc_parse_optionst::help() // NOLINTNEXTLINE(whitespace/line_length) " --java-max-vla-length limit the length of user-code-created arrays\n" // NOLINTNEXTLINE(whitespace/line_length) + " --java-cp-include-files regexp of class files to load\n" " --java-unwind-enum-static try to unwind loops in static initialization of enums\n" "\n" "Semantic transformations:\n" diff --git a/src/cbmc/cbmc_parse_options.h b/src/cbmc/cbmc_parse_options.h index adc6e2ee517..a3fc5e7e7d3 100644 --- a/src/cbmc/cbmc_parse_options.h +++ b/src/cbmc/cbmc_parse_options.h @@ -55,6 +55,7 @@ class optionst; "(round-to-nearest)(round-to-plus-inf)(round-to-minus-inf)(round-to-zero)" \ "(graphml-witness):" \ "(java-max-vla-length):(java-unwind-enum-static)" \ + "(java-cp-include-files):" \ "(localize-faults)(localize-faults-method):" \ "(lazy-methods)" \ "(fixedbv)(floatbv)(all-claims)(all-properties)" // legacy, and will eventually disappear // NOLINT(whitespace/line_length) diff --git a/src/java_bytecode/jar_file.cpp b/src/java_bytecode/jar_file.cpp index d679f21c070..f7cb0726494 100644 --- a/src/java_bytecode/jar_file.cpp +++ b/src/java_bytecode/jar_file.cpp @@ -9,8 +9,8 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include - #include "jar_file.h" +#include /*******************************************************************\ @@ -24,7 +24,7 @@ Function: jar_filet::open \*******************************************************************/ -void jar_filet::open(const std::string &filename) +void jar_filet::open(std::string &java_cp_include_files, const std::string &filename) { if(!mz_ok) { @@ -38,8 +38,7 @@ void jar_filet::open(const std::string &filename) std::size_t number_of_files= mz_zip_reader_get_num_files(&zip); - index.reserve(number_of_files); - + size_t filtered_index=0; for(std::size_t i=0; i buffer; size_t bufsize=file_stat.m_uncomp_size; buffer.resize(bufsize); mz_bool read_ok= - mz_zip_reader_extract_to_mem(&zip, i, buffer.data(), bufsize, 0); + mz_zip_reader_extract_to_mem(&zip, real_index, buffer.data(), bufsize, 0); if(read_ok!=MZ_TRUE) return std::string(); diff --git a/src/java_bytecode/jar_file.h b/src/java_bytecode/jar_file.h index 53f673102bf..7670cbf6a8b 100644 --- a/src/java_bytecode/jar_file.h +++ b/src/java_bytecode/jar_file.h @@ -15,27 +15,26 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include class jar_filet { public: jar_filet():mz_ok(false) { } - - inline explicit jar_filet(const std::string &file_name) - { - open(file_name); - } + inline explicit jar_filet(const std::string &file_name) { } ~jar_filet(); - void open(const std::string &); + void open(std::string &java_cp_include_files, const std::string &); // Test for error; 'true' means we are good. - inline explicit operator bool() const { return true; // TODO - } + inline explicit operator bool() const { return mz_ok; } typedef std::vector indext; indext index; + // map internal index to real index in jar central directory + typedef std::map filtered_jart; + filtered_jart filtered_jar; std::string get_entry(std::size_t i); @@ -45,18 +44,25 @@ class jar_filet protected: mz_zip_archive zip; bool mz_ok; + std::string matcher; + std::map index_map; }; class jar_poolt { public: + void set_java_cp_include_files(std::string &_java_cp_include_files) + { + java_cp_include_files=_java_cp_include_files; + } jar_filet &operator()(const std::string &file_name) { + assert(!java_cp_include_files.empty() && "class regexp cannot be empty"); file_mapt::iterator it=file_map.find(file_name); if(it==file_map.end()) { jar_filet &jar_file=file_map[file_name]; - jar_file.open(file_name); + jar_file.open(java_cp_include_files, file_name); return jar_file; } else @@ -66,6 +72,7 @@ class jar_poolt protected: typedef std::map file_mapt; file_mapt file_map; + std::string java_cp_include_files; }; #endif // CPROVER_JAVA_BYTECODE_JAR_FILE_H diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index 37ed835eca0..22f15aa8447 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -55,6 +55,10 @@ void java_bytecode_languaget::get_language_options(const cmdlinet &cmd) lazy_methods_mode=LAZY_METHODS_MODE_CONTEXT_INSENSITIVE; else lazy_methods_mode=LAZY_METHODS_MODE_EAGER; + if(cmd.isset("java-cp-include-files")) + java_cp_include_files=cmd.get_value("java-cp-include-files"); + else + java_cp_include_files=".*"; } /*******************************************************************\ @@ -129,6 +133,7 @@ bool java_bytecode_languaget::parse( const std::string &path) { java_class_loader.set_message_handler(get_message_handler()); + java_class_loader.set_java_cp_include_files(java_cp_include_files); // look at extension if(has_suffix(path, ".class")) diff --git a/src/java_bytecode/java_bytecode_language.h b/src/java_bytecode/java_bytecode_language.h index 48f45e2d39e..b3bdc8a5aa1 100644 --- a/src/java_bytecode/java_bytecode_language.h +++ b/src/java_bytecode/java_bytecode_language.h @@ -105,6 +105,7 @@ class java_bytecode_languaget:public languaget lazy_methodst lazy_methods; lazy_methods_modet lazy_methods_mode; bool string_refinement_enabled; + std::string java_cp_include_files; }; languaget *new_java_bytecode_language(); diff --git a/src/java_bytecode/java_class_loader.h b/src/java_bytecode/java_class_loader.h index b2a4953445a..8e8f5c5b82c 100644 --- a/src/java_bytecode/java_class_loader.h +++ b/src/java_bytecode/java_class_loader.h @@ -20,6 +20,10 @@ class java_class_loadert:public messaget { public: java_bytecode_parse_treet &operator()(const irep_idt &); + void set_java_cp_include_files(std::string &java_cp_include_files) + { + jar_pool.set_java_cp_include_files(java_cp_include_files); + } // maps class names to the parse trees typedef std::map class_mapt; From 6de183b7d18be96916ac713a122aba47d8eefef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Tue, 7 Mar 2017 13:04:24 +0100 Subject: [PATCH 115/699] support class load configuration via JSON file e.g. ``` { "jar": [ "A.jar", "B.jar" ], "classFiles": [ "jarfile3$A.class", "jarfile3.class" ] } ``` --- src/cbmc/Makefile | 4 +-- src/cbmc/cbmc_parse_options.cpp | 2 +- src/cegis/Makefile | 4 +-- src/goto-cc/Makefile | 3 +- src/goto-diff/Makefile | 3 +- src/goto-instrument/Makefile | 3 +- src/java_bytecode/jar_file.cpp | 50 ++++++++++++++++++++++----- src/java_bytecode/jar_file.h | 6 ++-- src/java_bytecode/java_class_loader.h | 1 + src/symex/Makefile | 3 +- 10 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/cbmc/Makefile b/src/cbmc/Makefile index 4fdb5338e41..8132097565c 100644 --- a/src/cbmc/Makefile +++ b/src/cbmc/Makefile @@ -28,8 +28,8 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \ ../assembler/assembler$(LIBEXT) \ ../solvers/solvers$(LIBEXT) \ ../util/util$(LIBEXT) \ - ../json/json$(LIBEXT) \ - ../miniz/miniz$(OBJEXT) + ../miniz/miniz$(OBJEXT) \ + ../json/json$(LIBEXT) INCLUDES= -I .. diff --git a/src/cbmc/cbmc_parse_options.cpp b/src/cbmc/cbmc_parse_options.cpp index 069034fa7a6..4c080b10ceb 100644 --- a/src/cbmc/cbmc_parse_options.cpp +++ b/src/cbmc/cbmc_parse_options.cpp @@ -1158,7 +1158,7 @@ void cbmc_parse_optionst::help() // NOLINTNEXTLINE(whitespace/line_length) " --java-max-vla-length limit the length of user-code-created arrays\n" // NOLINTNEXTLINE(whitespace/line_length) - " --java-cp-include-files regexp of class files to load\n" + " --java-cp-include-files regexp or JSON list of files to load (with '@' prefix)\n" " --java-unwind-enum-static try to unwind loops in static initialization of enums\n" "\n" "Semantic transformations:\n" diff --git a/src/cegis/Makefile b/src/cegis/Makefile index be519a9e8a1..f1a38ce4915 100644 --- a/src/cegis/Makefile +++ b/src/cegis/Makefile @@ -116,8 +116,8 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \ ../cbmc/cbmc_dimacs$(OBJEXT) ../cbmc/all_properties$(OBJEXT) \ ../cbmc/fault_localization$(OBJEXT) \ ../cbmc/symex_coverage$(OBJEXT) \ - ../json/json$(LIBEXT) \ - ../miniz/miniz$(OBJEXT) + ../miniz/miniz$(OBJEXT) \ + ../json/json$(LIBEXT) INCLUDES= -I .. diff --git a/src/goto-cc/Makefile b/src/goto-cc/Makefile index 04261db95f0..3079e7ebb00 100644 --- a/src/goto-cc/Makefile +++ b/src/goto-cc/Makefile @@ -14,7 +14,8 @@ OBJ += ../big-int/big-int$(LIBEXT) \ ../xmllang/xmllang$(LIBEXT) \ ../assembler/assembler$(LIBEXT) \ ../langapi/langapi$(LIBEXT) \ - ../miniz/miniz$(OBJEXT) + ../miniz/miniz$(OBJEXT) \ + ../json/json$(LIBEXT) INCLUDES= -I .. diff --git a/src/goto-diff/Makefile b/src/goto-diff/Makefile index c003d0c96b0..fd18897aaea 100644 --- a/src/goto-diff/Makefile +++ b/src/goto-diff/Makefile @@ -14,7 +14,8 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \ ../xmllang/xmllang$(LIBEXT) \ ../util/util$(LIBEXT) \ ../solvers/solvers$(LIBEXT) \ - ../miniz/miniz$(OBJEXT) + ../miniz/miniz$(OBJEXT) \ + ../json/json$(LIBEXT) INCLUDES= -I .. diff --git a/src/goto-instrument/Makefile b/src/goto-instrument/Makefile index 571bdf90eb9..b706e789c29 100644 --- a/src/goto-instrument/Makefile +++ b/src/goto-instrument/Makefile @@ -39,7 +39,8 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \ ../util/util$(LIBEXT) \ ../json/json$(LIBEXT) \ ../solvers/solvers$(LIBEXT) \ - ../miniz/miniz$(OBJEXT) + ../miniz/miniz$(OBJEXT) \ + ../json/json$(LIBEXT) INCLUDES= -I .. diff --git a/src/java_bytecode/jar_file.cpp b/src/java_bytecode/jar_file.cpp index f7cb0726494..0f45af67d33 100644 --- a/src/java_bytecode/jar_file.cpp +++ b/src/java_bytecode/jar_file.cpp @@ -8,10 +8,11 @@ Author: Daniel Kroening, kroening@kroening.com #include #include -#include +#include +#include #include "jar_file.h" #include - +#include /*******************************************************************\ Function: jar_filet::open @@ -24,7 +25,9 @@ Function: jar_filet::open \*******************************************************************/ -void jar_filet::open(std::string &java_cp_include_files, const std::string &filename) +void jar_filet::open( + std::string &java_cp_include_files, + const std::string &filename) { if(!mz_ok) { @@ -35,6 +38,32 @@ void jar_filet::open(std::string &java_cp_include_files, const std::string &file if(mz_ok) { + // '@' signals file reading with list of class files to load + bool regex_match=java_cp_include_files[0]!='@'; + std::regex regex_matcher; + std::smatch string_matcher; + std::unordered_set set_matcher; + jsont json_cp_config; + if(regex_match) + regex_matcher=std::regex(java_cp_include_files); + else + { + assert(java_cp_include_files.length()>1); + if(parse_json( + java_cp_include_files.substr(1), + get_message_handler(), + json_cp_config)) + throw "cannot read JSON input configuration for JAR loading"; + assert(json_cp_config.is_object() && "JSON has wrong format"); + jsont include_files=json_cp_config["classFiles"]; + assert(include_files.is_array() && "JSON has wrong format"); + for(const jsont &file_entry : include_files.array) + { + assert(file_entry.is_string()); + set_matcher.insert(file_entry.value); + } + } + std::size_t number_of_files= mz_zip_reader_get_num_files(&zip); @@ -47,11 +76,16 @@ void jar_filet::open(std::string &java_cp_include_files, const std::string &file mz_zip_reader_get_filename(&zip, i, filename_char, filename_length); assert(filename_length==filename_len); std::string file_name(filename_char); - std::smatch string_matcher; - std::regex matcher(java_cp_include_files); - // load .class files only if they match regex - if(std::regex_match(file_name, string_matcher, matcher) || - !has_suffix(file_name, ".class")) + + // non-class files are loaded in any case + bool add_file=!has_suffix(file_name, ".class"); + // load .class file only if they match regex + if(regex_match) + add_file|=std::regex_match(file_name, string_matcher, regex_matcher); + // load .class file only if it is in the match set + else + add_file|=set_matcher.count(file_name)>0; + if(add_file) { index.push_back(file_name); filtered_jar[filtered_index]=i; diff --git a/src/java_bytecode/jar_file.h b/src/java_bytecode/jar_file.h index 7670cbf6a8b..a1ff04bb933 100644 --- a/src/java_bytecode/jar_file.h +++ b/src/java_bytecode/jar_file.h @@ -16,8 +16,9 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include -class jar_filet +class jar_filet:public messaget { public: jar_filet():mz_ok(false) { } @@ -48,7 +49,7 @@ class jar_filet std::map index_map; }; -class jar_poolt +class jar_poolt:public messaget { public: void set_java_cp_include_files(std::string &_java_cp_include_files) @@ -62,6 +63,7 @@ class jar_poolt if(it==file_map.end()) { jar_filet &jar_file=file_map[file_name]; + jar_file.set_message_handler(get_message_handler()); jar_file.open(java_cp_include_files, file_name); return jar_file; } diff --git a/src/java_bytecode/java_class_loader.h b/src/java_bytecode/java_class_loader.h index 8e8f5c5b82c..e76d5894860 100644 --- a/src/java_bytecode/java_class_loader.h +++ b/src/java_bytecode/java_class_loader.h @@ -23,6 +23,7 @@ class java_class_loadert:public messaget void set_java_cp_include_files(std::string &java_cp_include_files) { jar_pool.set_java_cp_include_files(java_cp_include_files); + jar_pool.set_message_handler(get_message_handler()); } // maps class names to the parse trees diff --git a/src/symex/Makefile b/src/symex/Makefile index e152b2461bf..51b672e7a72 100644 --- a/src/symex/Makefile +++ b/src/symex/Makefile @@ -18,7 +18,8 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \ ../goto-instrument/cover$(OBJEXT) \ ../json/json$(LIBEXT) \ ../path-symex/path-symex$(LIBEXT) \ - ../miniz/miniz$(OBJEXT) + ../miniz/miniz$(OBJEXT) \ + ../json/json$(LIBEXT) INCLUDES= -I .. From 898ba0c1e9a549a9c740b756331f9b1cce62d6a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Tue, 7 Mar 2017 13:32:27 +0100 Subject: [PATCH 116/699] add jars from JSON config to classpath --- src/java_bytecode/java_bytecode_language.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index 22f15aa8447..620b3c17129 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -13,6 +13,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include #include @@ -59,6 +60,25 @@ void java_bytecode_languaget::get_language_options(const cmdlinet &cmd) java_cp_include_files=cmd.get_value("java-cp-include-files"); else java_cp_include_files=".*"; + // load file list from JSON file + if(java_cp_include_files[0]=='@') + { + jsont json_cp_config; + if(parse_json( + java_cp_include_files.substr(1), + get_message_handler(), + json_cp_config)) + throw "cannot read JSON input configuration for JAR loading"; + assert(json_cp_config.is_object() && "JSON has wrong format"); + jsont include_files=json_cp_config["jar"]; + assert(include_files.is_array() && "JSON has wrong format"); + // add jars from JSON config file to classpath + for(const jsont &file_entry : include_files.array) + { + assert(file_entry.is_string() && has_suffix(file_entry.value, ".jar")); + config.java.classpath.push_back(file_entry.value); + } + } } /*******************************************************************\ From 52952bb688f6dad6e8492dc11bfcc39cff7c471a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Tue, 7 Mar 2017 14:51:08 +0100 Subject: [PATCH 117/699] add regression test --- regression/cbmc-java/jar-file4/A.jar | Bin 0 -> 721 bytes regression/cbmc-java/jar-file4/B.jar | Bin 0 -> 721 bytes regression/cbmc-java/jar-file4/C.jar | Bin 0 -> 934 bytes regression/cbmc-java/jar-file4/jar.json | 12 ++++++++++++ regression/cbmc-java/jar-file4/test.desc | 10 ++++++++++ 5 files changed, 22 insertions(+) create mode 100644 regression/cbmc-java/jar-file4/A.jar create mode 100644 regression/cbmc-java/jar-file4/B.jar create mode 100644 regression/cbmc-java/jar-file4/C.jar create mode 100644 regression/cbmc-java/jar-file4/jar.json create mode 100644 regression/cbmc-java/jar-file4/test.desc diff --git a/regression/cbmc-java/jar-file4/A.jar b/regression/cbmc-java/jar-file4/A.jar new file mode 100644 index 0000000000000000000000000000000000000000..e721e6f32f945341ca9aafca44a794bb16cfeb02 GIT binary patch literal 721 zcmWIWW@Zs#;Nak3$Pf4PVn70%3@i-3t|5-Po_=on|4uP5Ff#;rvvYt{FhP|C;M6Pv zQ~}rQ>*(j{<{BKL=j-;__snS@Z(Y5MyxzK6=gyqp9At3C_`%a6JuhD!Pv48Bt5`TA zUPvC1mXg%U_#v*U_I!z!#dC4dC*rEp7_Mf2D*9N&2zG^l;4&o_pdGG2jBrIdnim9s zvRR2mX_+~x#ww0_$vKI|#jgIo-iI9oYA>t!?p9O#8lCUNZ`vBR!Q6F1Q-DTQz@Ge9 ztE3-^O$zxFE!Xwnp!|b=p>*bhhozrA-fM1bzd!yygPO&wL#{dx7N&33mAAJ0#`)#k z48dDhyY+rAXE8jV@^MLVY1z5E+_@#Co*eA|-%e(4vW~UWax%H@c6Uu&aOj=WCeQnJ zM6c^=-F0mnhxA#E$@xYO>~|TM*coqqsFg9=oA_n@4?Z^oV>i*uG1Hc6ac>E6$vE ze0%0HG0}sPH<+z@1&;seJ8r*CB8U6P#@HjG)}OZV_A!P#r$zWp;kmxxiSXJZv4?-I z=u~tM?3bNZH7EDlG{JALIO}_I-!%OL2i}6vmH++&gC>v>6nKnGA`GZ002aNV6o3lg zQ3^^A=vtBE1Qh=WU<+izwIZbkWD`JfhwLy=+#$eWAQL?%1H4(;Kq{Dla5snnb~gZw CHqIXa literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/jar-file4/B.jar b/regression/cbmc-java/jar-file4/B.jar new file mode 100644 index 0000000000000000000000000000000000000000..d381e413e74f2aa5d1f92381ec7fe608679b7e81 GIT binary patch literal 721 zcmWIWW@Zs#;Nak3C=U1YVn70%3@i-3t|5-Po_=on|4uP5Ff#;rvvYt{FhP|C;M6Pv zQ~}rQ>*(j{<{BKL=j-;__snS@Z(Y5MyxzK6=gyqp9At3C_`%a6JuhD!Pv48Bt5`TA zUPvC1mXg%U_#v*U_I!z!#dC4dC*rEp7_Mf2D*9N&2zG^l;4&o_pdGG2jBrIdnim9s zvRR2mX_+~x#wt#F$vKI|#jgIo-iI9oYA-Lln|61`kH3Y&RVy^NG~E;77i)34*!-wA zIQ*_aut(6x{7Q``_WA~UuQ|Ld{P{Ebzu!Ca=TBWNv&G?s{QMJL*roMui`)>qp?twQ z+3Q7^{^b@9qQIepCtu>P_P*wY%PRA_JeQrmG^OPP=kb~6 z<{#hgne|L`p=|;C7b(TQA9MNs-$>e^E8v)Or~%rTH#=kQTIYU6gN z-;34QWKwO#biP_fuh(^cb4~c4MDz{Dzl@+Lv^lv+>OU}O0vSPp$H*kYfSLke(F;le zr~n?Np!9&Q6**2o@s9wuKqg!(Qffdp0Tg%04g*(j{<{BKL=j-;__snS@Z(Y5MyxzK6=gyqp9At3C_`%a6JuhD!Pv48Bt5`TA zUPvC1mXg%U_#v*U_I!z!#dC4dC*rEp7_Mf2D*9N&2zG^l;4&o_pdGG2jBv&AXjCuo z0cEoii_$W4QjPVJa}tY-eS>2Cg&jp~H{UJWEkD(1={5c%UKd##XPubMqPxOV*iOzs z?ZdWQ_RU-K&c3uq&??>SSR&rJv ziT4i4va`JsduL@3xcy<$LA6U8HoRESQ90Yd{JYGZ_WVRohaAp|w;GeOss)a0?BU$X zqQ$#6(9@#lQF@|G3EQUQXC^u%D)$^p308QnzgNg$d%LZs!B%0nqWmx0l&^aGs(qi~ zxqq$Y(q@$x`)=~yTdKKhiDTmn2TX z?49N|O)EjJ&w%(^$lVXOM%fRp!H`EL8T6;>I$ulW4QyGAB(U1oJpk-#p=bDQs+ zEfkIUd^%kq-b66;T&u{H$5L6(uk`Df?zEFUY@uSi-MVdM^PhX+B7OmpmaVCEP1bH7 zKk$58|Nq4+%{ix6h#3Y=)cQ1M{efd5bEiJM{7`N2YZqII`Y-o)BtCqm^Z(3R?&Ggl z>Lyej`^)#fWzzh_XZsc!SXvaX=RbA$!#pmvXP3U@W;IH&MHjAIYpl2Rs68lU{uE0H zyurx8a1@w41H2iTL>N#LHZ0YG5;iJ;r&LffN7ss+)IiA^0c?RxxK^Y@j%)%bNg_K8 clq3=0Fp!CwKm)v4*+BBlK)4e~UkAGy09`dfUjP6A literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/jar-file4/jar.json b/regression/cbmc-java/jar-file4/jar.json new file mode 100644 index 00000000000..09df8008b8c --- /dev/null +++ b/regression/cbmc-java/jar-file4/jar.json @@ -0,0 +1,12 @@ +{ + "jar": + [ + "A.jar", + "B.jar" + ], + "classFiles": + [ + "jarfile3$A.class", + "jarfile3.class" + ] +} diff --git a/regression/cbmc-java/jar-file4/test.desc b/regression/cbmc-java/jar-file4/test.desc new file mode 100644 index 00000000000..5c34bdcd5a8 --- /dev/null +++ b/regression/cbmc-java/jar-file4/test.desc @@ -0,0 +1,10 @@ +CORE +C.jar +--function jarfile3.f --java-cp-include-files "@jar.json" +^EXIT=10$ +^SIGNAL=0$ +.*SUCCESS$ +.*FAILURE$ +^VERIFICATION FAILED +-- +^warning: ignoring From aec47b7000f45ea5f5f0986b93853e2942810c88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Fri, 10 Mar 2017 11:18:52 +0100 Subject: [PATCH 118/699] take comments into account --- src/java_bytecode/jar_file.cpp | 14 ++++--- src/java_bytecode/jar_file.h | 9 ++-- src/java_bytecode/java_bytecode_language.cpp | 43 ++++++++++++-------- src/java_bytecode/java_class_loader.h | 1 + 4 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/java_bytecode/jar_file.cpp b/src/java_bytecode/jar_file.cpp index 0f45af67d33..0980e1466ea 100644 --- a/src/java_bytecode/jar_file.cpp +++ b/src/java_bytecode/jar_file.cpp @@ -8,11 +8,11 @@ Author: Daniel Kroening, kroening@kroening.com #include #include -#include #include -#include "jar_file.h" + +#include #include -#include +#include "jar_file.h" /*******************************************************************\ Function: jar_filet::open @@ -54,9 +54,11 @@ void jar_filet::open( get_message_handler(), json_cp_config)) throw "cannot read JSON input configuration for JAR loading"; - assert(json_cp_config.is_object() && "JSON has wrong format"); + if(!json_cp_config.is_object()) + throw "the JSON file has a wrong format"; jsont include_files=json_cp_config["classFiles"]; - assert(include_files.is_array() && "JSON has wrong format"); + if(!include_files.is_array()) + throw "the JSON file has a wrong format"; for(const jsont &file_entry : include_files.array) { assert(file_entry.is_string()); @@ -84,7 +86,7 @@ void jar_filet::open( add_file|=std::regex_match(file_name, string_matcher, regex_matcher); // load .class file only if it is in the match set else - add_file|=set_matcher.count(file_name)>0; + add_file|=set_matcher.find(file_name)!=set_matcher.end(); if(add_file) { index.push_back(file_name); diff --git a/src/java_bytecode/jar_file.h b/src/java_bytecode/jar_file.h index a1ff04bb933..c168b8b4199 100644 --- a/src/java_bytecode/jar_file.h +++ b/src/java_bytecode/jar_file.h @@ -22,14 +22,13 @@ class jar_filet:public messaget { public: jar_filet():mz_ok(false) { } - inline explicit jar_filet(const std::string &file_name) { } ~jar_filet(); void open(std::string &java_cp_include_files, const std::string &); // Test for error; 'true' means we are good. - inline explicit operator bool() const { return mz_ok; } + explicit operator bool() const { return mz_ok; } typedef std::vector indext; indext index; @@ -45,8 +44,6 @@ class jar_filet:public messaget protected: mz_zip_archive zip; bool mz_ok; - std::string matcher; - std::map index_map; }; class jar_poolt:public messaget @@ -56,9 +53,11 @@ class jar_poolt:public messaget { java_cp_include_files=_java_cp_include_files; } + jar_filet &operator()(const std::string &file_name) { - assert(!java_cp_include_files.empty() && "class regexp cannot be empty"); + if(java_cp_include_files.empty()) + throw "class regexp cannot be empty"; file_mapt::iterator it=file_map.find(file_name); if(it==file_map.end()) { diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index 620b3c17129..9faa16f676a 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -56,29 +56,36 @@ void java_bytecode_languaget::get_language_options(const cmdlinet &cmd) lazy_methods_mode=LAZY_METHODS_MODE_CONTEXT_INSENSITIVE; else lazy_methods_mode=LAZY_METHODS_MODE_EAGER; + if(cmd.isset("java-cp-include-files")) - java_cp_include_files=cmd.get_value("java-cp-include-files"); - else - java_cp_include_files=".*"; - // load file list from JSON file - if(java_cp_include_files[0]=='@') { - jsont json_cp_config; - if(parse_json( - java_cp_include_files.substr(1), - get_message_handler(), - json_cp_config)) - throw "cannot read JSON input configuration for JAR loading"; - assert(json_cp_config.is_object() && "JSON has wrong format"); - jsont include_files=json_cp_config["jar"]; - assert(include_files.is_array() && "JSON has wrong format"); - // add jars from JSON config file to classpath - for(const jsont &file_entry : include_files.array) + java_cp_include_files=cmd.get_value("java-cp-include-files"); + // load file list from JSON file + if(java_cp_include_files[0]=='@') { - assert(file_entry.is_string() && has_suffix(file_entry.value, ".jar")); - config.java.classpath.push_back(file_entry.value); + jsont json_cp_config; + if(parse_json( + java_cp_include_files.substr(1), + get_message_handler(), + json_cp_config)) + throw "cannot read JSON input configuration for JAR loading"; + + if(!json_cp_config.is_object()) + throw "the JSON file has a wrong format"; + jsont include_files=json_cp_config["jar"]; + if(!include_files.is_array()) + throw "the JSON file has a wrong format"; + + // add jars from JSON config file to classpath + for(const jsont &file_entry : include_files.array) + { + assert(file_entry.is_string() && has_suffix(file_entry.value, ".jar")); + config.java.classpath.push_back(file_entry.value); + } } } + else + java_cp_include_files=".*"; } /*******************************************************************\ diff --git a/src/java_bytecode/java_class_loader.h b/src/java_bytecode/java_class_loader.h index e76d5894860..dfd57ac9ac7 100644 --- a/src/java_bytecode/java_class_loader.h +++ b/src/java_bytecode/java_class_loader.h @@ -20,6 +20,7 @@ class java_class_loadert:public messaget { public: java_bytecode_parse_treet &operator()(const irep_idt &); + void set_java_cp_include_files(std::string &java_cp_include_files) { jar_pool.set_java_cp_include_files(java_cp_include_files); From 039ac4d8cade36ed90d0fb532c4bfe109e673893 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Fri, 10 Mar 2017 14:10:38 +0100 Subject: [PATCH 119/699] change from vector indices to map --- src/java_bytecode/jar_file.cpp | 36 +++++++++---------------- src/java_bytecode/jar_file.h | 6 ++--- src/java_bytecode/java_class_loader.cpp | 11 ++++---- src/java_bytecode/java_class_loader.h | 2 +- 4 files changed, 20 insertions(+), 35 deletions(-) diff --git a/src/java_bytecode/jar_file.cpp b/src/java_bytecode/jar_file.cpp index 0980e1466ea..07d7719e500 100644 --- a/src/java_bytecode/jar_file.cpp +++ b/src/java_bytecode/jar_file.cpp @@ -69,7 +69,6 @@ void jar_filet::open( std::size_t number_of_files= mz_zip_reader_get_num_files(&zip); - size_t filtered_index=0; for(std::size_t i=0; isecond; mz_zip_archive_file_stat file_stat; memset(&file_stat, 0, sizeof(file_stat)); mz_bool stat_ok=mz_zip_reader_file_stat(&zip, real_index, &file_stat); @@ -173,24 +174,11 @@ Function: jar_filet::get_manifest jar_filet::manifestt jar_filet::get_manifest() { - std::size_t i=0; - bool found=false; - - for(const auto &e : index) - { - if(e=="META-INF/MANIFEST.MF") - { - found=true; - break; - } - - i++; - } - - if(!found) + auto entry=filtered_jar.find("META-INF/MANIFEST.MF"); + if(entry==filtered_jar.end()) return manifestt(); - std::string dest=get_entry(i); + std::string dest=get_entry(entry->first); std::istringstream in(dest); manifestt manifest; diff --git a/src/java_bytecode/jar_file.h b/src/java_bytecode/jar_file.h index c168b8b4199..9407e711128 100644 --- a/src/java_bytecode/jar_file.h +++ b/src/java_bytecode/jar_file.h @@ -30,13 +30,11 @@ class jar_filet:public messaget // Test for error; 'true' means we are good. explicit operator bool() const { return mz_ok; } - typedef std::vector indext; - indext index; // map internal index to real index in jar central directory - typedef std::map filtered_jart; + typedef std::map filtered_jart; filtered_jart filtered_jar; - std::string get_entry(std::size_t i); + std::string get_entry(const irep_idt &); typedef std::map manifestt; manifestt get_manifest(); diff --git a/src/java_bytecode/java_class_loader.cpp b/src/java_bytecode/java_class_loader.cpp index dc4330aa00c..c8e6bbf5bb4 100644 --- a/src/java_bytecode/java_class_loader.cpp +++ b/src/java_bytecode/java_class_loader.cpp @@ -98,7 +98,7 @@ java_bytecode_parse_treet &java_class_loadert::get_parse_tree( debug() << "Getting class `" << class_name << "' from JAR " << jf << eom; - std::string data=jar_pool(jf).get_entry(jm_it->second.index); + std::string data=jar_pool(jf).get_entry(jm_it->second.class_file_name); std::istringstream istream(data); @@ -129,7 +129,7 @@ java_bytecode_parse_treet &java_class_loadert::get_parse_tree( debug() << "Getting class `" << class_name << "' from JAR " << cp << eom; - std::string data=jar_pool(cp).get_entry(jm_it->second.index); + std::string data=jar_pool(cp).get_entry(jm_it->second.class_file_name); std::istringstream istream(data); @@ -223,11 +223,10 @@ void java_class_loadert::read_jar_file(const irep_idt &file) debug() << "adding JAR file `" << file << "'" << eom; auto &jm=jar_map[file]; - std::size_t number_of_files=jar_file.index.size(); - for(std::size_t i=0; i Date: Thu, 16 Feb 2017 16:36:33 +0000 Subject: [PATCH 120/699] Explore matching nested bracketed stuff --- scripts/cpplint.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/cpplint.py b/scripts/cpplint.py index 3d457bb4113..62c2f93b09b 100755 --- a/scripts/cpplint.py +++ b/scripts/cpplint.py @@ -552,7 +552,9 @@ "Missing space before {": r's/\([^ ]\){/\1 {/', "Tab found, replace by spaces": r's/\t/ /', "Line ends in whitespace. Consider deleting these extra spaces.": r's/\s*$//', - #"Redundant blank line at the end of a code block should be deleted.": "d", # messes up line numbers for other errors. + # "Statement after an if should be on a new line": r's/^\(\s*\)if *\(([^()]*)\) *\(.*\)$/\1if\2\n\1 \3/', # Single layer of nested bracets + # "Statement after an if should be on a new line": r's/^\(\s*\)if *\((\([^()]\|([^()]*)\)*)\) *\(.*\)$/\1if\2\n\1 \4/', # Max 2 layers of nested bracets; messes up line numbers for other errors. + # "Redundant blank line at the end of a code block should be deleted.": "d", # messes up line numbers for other errors. } _regexp_compile_cache = {} From 32f91b828f2df865407f3712eb714a039c8b9d2d Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Mon, 20 Feb 2017 00:50:11 +0000 Subject: [PATCH 121/699] Fix ; after } errors --- scripts/cpplint.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/cpplint.py b/scripts/cpplint.py index 62c2f93b09b..94b30c3851a 100755 --- a/scripts/cpplint.py +++ b/scripts/cpplint.py @@ -552,6 +552,7 @@ "Missing space before {": r's/\([^ ]\){/\1 {/', "Tab found, replace by spaces": r's/\t/ /', "Line ends in whitespace. Consider deleting these extra spaces.": r's/\s*$//', + "You don't need a ; after a }": r's/};/}/', # "Statement after an if should be on a new line": r's/^\(\s*\)if *\(([^()]*)\) *\(.*\)$/\1if\2\n\1 \3/', # Single layer of nested bracets # "Statement after an if should be on a new line": r's/^\(\s*\)if *\((\([^()]\|([^()]*)\)*)\) *\(.*\)$/\1if\2\n\1 \4/', # Max 2 layers of nested bracets; messes up line numbers for other errors. # "Redundant blank line at the end of a code block should be deleted.": "d", # messes up line numbers for other errors. From 0f69c9341527461005efe95dbbe92d75f1176201 Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Mon, 20 Feb 2017 11:01:20 +0000 Subject: [PATCH 122/699] Fix missing space after , errors --- scripts/cpplint.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/cpplint.py b/scripts/cpplint.py index 94b30c3851a..3dfb5f4326c 100755 --- a/scripts/cpplint.py +++ b/scripts/cpplint.py @@ -553,6 +553,7 @@ "Tab found, replace by spaces": r's/\t/ /', "Line ends in whitespace. Consider deleting these extra spaces.": r's/\s*$//', "You don't need a ; after a }": r's/};/}/', + "Missing space after ,": r's/,\([^ ]\)/, \1/', # "Statement after an if should be on a new line": r's/^\(\s*\)if *\(([^()]*)\) *\(.*\)$/\1if\2\n\1 \3/', # Single layer of nested bracets # "Statement after an if should be on a new line": r's/^\(\s*\)if *\((\([^()]\|([^()]*)\)*)\) *\(.*\)$/\1if\2\n\1 \4/', # Max 2 layers of nested bracets; messes up line numbers for other errors. # "Redundant blank line at the end of a code block should be deleted.": "d", # messes up line numbers for other errors. From f1a99f78f22018d76db6a3fd798cc6c8d05de8c3 Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Mon, 20 Feb 2017 11:13:14 +0000 Subject: [PATCH 123/699] Replace tabs globally within the line --- scripts/cpplint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cpplint.py b/scripts/cpplint.py index 3dfb5f4326c..0c366c78a1e 100755 --- a/scripts/cpplint.py +++ b/scripts/cpplint.py @@ -550,7 +550,7 @@ "Remove space before ( in switch (": "s/switch (/switch(/", "Should have a space between // and comment": 's/\/\//\/\/ /', "Missing space before {": r's/\([^ ]\){/\1 {/', - "Tab found, replace by spaces": r's/\t/ /', + "Tab found, replace by spaces": r's/\t/ /g', "Line ends in whitespace. Consider deleting these extra spaces.": r's/\s*$//', "You don't need a ; after a }": r's/};/}/', "Missing space after ,": r's/,\([^ ]\)/, \1/', From 5baa807a63b1d64168009e93e171727e0bad3c4f Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Fri, 3 Mar 2017 10:22:19 +0000 Subject: [PATCH 124/699] Add space after comma globally within the line --- scripts/cpplint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cpplint.py b/scripts/cpplint.py index 0c366c78a1e..52350b4923f 100755 --- a/scripts/cpplint.py +++ b/scripts/cpplint.py @@ -553,7 +553,7 @@ "Tab found, replace by spaces": r's/\t/ /g', "Line ends in whitespace. Consider deleting these extra spaces.": r's/\s*$//', "You don't need a ; after a }": r's/};/}/', - "Missing space after ,": r's/,\([^ ]\)/, \1/', + "Missing space after ,": r's/,\([^ ]\)/, \1/g', # "Statement after an if should be on a new line": r's/^\(\s*\)if *\(([^()]*)\) *\(.*\)$/\1if\2\n\1 \3/', # Single layer of nested bracets # "Statement after an if should be on a new line": r's/^\(\s*\)if *\((\([^()]\|([^()]*)\)*)\) *\(.*\)$/\1if\2\n\1 \4/', # Max 2 layers of nested bracets; messes up line numbers for other errors. # "Redundant blank line at the end of a code block should be deleted.": "d", # messes up line numbers for other errors. From 712f94ff89b6e04158e1867d692497863cb3cdd4 Mon Sep 17 00:00:00 2001 From: martin Date: Fri, 10 Feb 2017 16:58:28 +0000 Subject: [PATCH 125/699] Remove the top variable from the cfg_dominator analysis. This variable is not used anywhere, it is not clear what it's purpose is and in profiling it was shown to be expensive. --- src/analyses/cfg_dominators.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/analyses/cfg_dominators.h b/src/analyses/cfg_dominators.h index 687d84e1416..1a4d6090f47 100644 --- a/src/analyses/cfg_dominators.h +++ b/src/analyses/cfg_dominators.h @@ -35,7 +35,6 @@ class cfg_dominators_templatet void operator()(P &program); - target_sett top; T entry_node; void output(std::ostream &) const; @@ -101,10 +100,6 @@ template void cfg_dominators_templatet::initialise(P &program) { cfg(program); - - // initialise top element - for(const auto &node : cfg.entry_map) - top.insert(cfg[node.second].PC); } /*******************************************************************\ From 0381aab5ef65158d936a2549d158cf7986ad726c Mon Sep 17 00:00:00 2001 From: Vlastimil Zeman Date: Fri, 10 Mar 2017 11:58:17 +0000 Subject: [PATCH 126/699] Support for Linux based on musl-libc. Change `#ifdef __linux__` and `#if defined(__linux__)` when it really means *linux with glibc*. To avoid failures and be more specific it is now adding `defined(__GLIBC__)` to check if `glibc` is present. --- regression/cpp/enum8/test.desc | 2 +- scripts/minisat-2.2.1-patch | 12 ++++++++++++ src/util/memory_info.cpp | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/regression/cpp/enum8/test.desc b/regression/cpp/enum8/test.desc index a003b07b93c..f935f5ace1b 100644 --- a/regression/cpp/enum8/test.desc +++ b/regression/cpp/enum8/test.desc @@ -1,6 +1,6 @@ CORE main.cpp - +--std=c++11 ^EXIT=0$ ^SIGNAL=0$ -- diff --git a/scripts/minisat-2.2.1-patch b/scripts/minisat-2.2.1-patch index ec0fa3e439d..f00ea308d59 100644 --- a/scripts/minisat-2.2.1-patch +++ b/scripts/minisat-2.2.1-patch @@ -196,3 +196,15 @@ diff -urN minisat-2.2.1/minisat/utils/ParseUtils.h minisat-2.2.1.patched/minisat int operator * () const { return (pos >= size) ? EOF : buf[pos]; } void operator ++ () { pos++; assureLookahead(); } +diff -urN minisat-2.2.1/minisat/utils/System.h minisat-2.2.1.patched/minisat/utils/System.h +--- minisat-2.2.1/minisat/utils/System.h 2017-02-21 18:23:22.727464369 +0000 ++++ minisat-2.2.1.patched/minisat/utils/System.h 2017-02-21 18:23:14.451343361 +0000 +@@ -21,7 +21,7 @@ + #ifndef Minisat_System_h + #define Minisat_System_h + +-#if defined(__linux__) ++#if defined(__linux__) && defined(__GLIBC__) + #include + #endif + diff --git a/src/util/memory_info.cpp b/src/util/memory_info.cpp index cb8b0161252..af4f2ef1d52 100644 --- a/src/util/memory_info.cpp +++ b/src/util/memory_info.cpp @@ -39,7 +39,7 @@ Function: memory_info void memory_info(std::ostream &out) { - #ifdef __linux__ + #if defined(__linux__) && defined(__GLIBC__) // NOLINTNEXTLINE(readability/identifiers) struct mallinfo m = mallinfo(); out << " non-mmapped space allocated from system: " << m.arena << "\n"; From dcd0c52df4c7221a657c186b6640d56dc3a76222 Mon Sep 17 00:00:00 2001 From: Vlastimil Zeman Date: Fri, 10 Mar 2017 12:03:46 +0000 Subject: [PATCH 127/699] Add test for Alpine linux (musl-libc). - new environment in matrix that run compilation in alpine docker container. - reordering matrix environments from the longest run to the shortest run time. - rewrite of `script` to be able to run compilation in a container if needed. --- .travis.yml | 51 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2f1c8103990..d74ec93f7e3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,35 @@ language: cpp -sudo: false - matrix: include: + + # Alpine Linux with musl-libc using g++ + - os: linux + sudo: required + compiler: gcc + services: + - docker + before_install: + - docker pull diffblue/cbmc-builder:alpine + env: + - PRE_COMMAND="docker run -v ${TRAVIS_BUILD_DIR}:/cbmc diffblue/cbmc-builder:alpine" + - COMPILER=g++ + + # OS X using g++ + - os: osx + sudo: false + compiler: gcc + env: COMPILER=g++ + + # OS X using clang++ + - os: osx + sudo: false + compiler: clang + env: COMPILER=clang++ + + # Ubuntu Linux with glibc using g++-5 - os: linux + sudo: false compiler: gcc addons: apt: @@ -18,7 +43,10 @@ matrix: - mkdir bin ; ln -s /usr/bin/gcc-5 bin/gcc # env: COMPILER=g++-5 SAN_FLAGS="-fsanitize=undefined -fno-sanitize-recover -fno-omit-frame-pointer" env: COMPILER=g++-5 + + # Ubuntu Linux with glibc using clang++-3.7 - os: linux + sudo: false compiler: clang addons: apt: @@ -34,18 +62,17 @@ matrix: - mkdir bin ; ln -s /usr/bin/clang-3.7 bin/gcc # env: COMPILER=clang++-3.7 SAN_FLAGS="-fsanitize=undefined -fno-sanitize-recover=undefined,integer -fno-omit-frame-pointer" env: COMPILER=clang++-3.7 - - os: osx - compiler: gcc - env: COMPILER=g++ - - os: osx - compiler: clang - env: COMPILER=clang++ + - env: NAME="CPP-LINT" script: scripts/travis_lint.sh || true script: - if [ -L bin/gcc ] ; then export PATH=$PWD/bin:$PATH ; fi ; - make -C src minisat2-download && - make -C src CXX=$COMPILER CXXFLAGS="-Wall -O2 -g -Werror -Wno-deprecated-register -pedantic -Wno-sign-compare" -j2 && - env UBSAN_OPTIONS=print_stacktrace=1 make -C regression test && - make -C src CXX=$COMPILER CXXFLAGS=$FLAGS -j2 cegis.dir clobber.dir memory-models.dir musketeer.dir + COMMAND="make -C src minisat2-download" && + eval ${PRE_COMMAND} ${COMMAND} && + COMMAND="make -C src CXX=$COMPILER CXXFLAGS=\"-Wall -O2 -g -Werror -Wno-deprecated-register -pedantic -Wno-sign-compare\" -j2" && + eval ${PRE_COMMAND} ${COMMAND} && + COMMAND="env UBSAN_OPTIONS=print_stacktrace=1 make -C regression test" && + eval ${PRE_COMMAND} ${COMMAND} && + COMMAND="make -C src CXX=$COMPILER CXXFLAGS=$FLAGS -j2 cegis.dir clobber.dir memory-models.dir musketeer.dir" && + eval ${PRE_COMMAND} ${COMMAND} From 1aede785e785904825ff3e62aa432b9e0ce585d4 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Sat, 31 Dec 2016 15:27:04 +0300 Subject: [PATCH 128/699] Preprocessing of goto programs for string refinement --- .../string_refine_preprocess.cpp | 1289 +++++++++++++++++ src/goto-programs/string_refine_preprocess.h | 215 +++ src/util/std_expr.h | 13 + 3 files changed, 1517 insertions(+) create mode 100644 src/goto-programs/string_refine_preprocess.cpp create mode 100644 src/goto-programs/string_refine_preprocess.h diff --git a/src/goto-programs/string_refine_preprocess.cpp b/src/goto-programs/string_refine_preprocess.cpp new file mode 100644 index 00000000000..c4dc1a92960 --- /dev/null +++ b/src/goto-programs/string_refine_preprocess.cpp @@ -0,0 +1,1289 @@ +/*******************************************************************\ + +Module: Preprocess a goto-programs so that calls to the java String + library are recognized by the string solver + +Author: Romain Brenguier + +Date: September 2016 + +\*******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +// TODO: refined_string_type should be moved to util +#include +#include + +#include "string_refine_preprocess.h" + +/******************************************************************* \ + +Function: string_refine_preprocesst::fresh_array + + Inputs: + type - an array type + location - a location in the program + + Outputs: a new symbol + + Purpose: add a symbol with static lifetime and name containing + `cprover_string_array` and given type + +\*******************************************************************/ + +symbol_exprt string_refine_preprocesst::fresh_array( + const typet &type, const source_locationt &location) +{ + symbolt array_symbol=get_fresh_aux_symbol( + type, + "cprover_string_array", + "cprover_string_array", + location, + ID_java, + symbol_table); + array_symbol.is_static_lifetime=true; + return array_symbol.symbol_expr(); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::fresh_string + + Inputs: + type - a type for refined strings + location - a location in the program + + Outputs: a new symbol + + Purpose: add a symbol with static lifetime and name containing + `cprover_string` and given type + +\*******************************************************************/ + +symbol_exprt string_refine_preprocesst::fresh_string( + const typet &type, const source_locationt &location) +{ + symbolt array_symbol=get_fresh_aux_symbol( + type, "cprover_string", "cprover_string", location, ID_java, symbol_table); + array_symbol.is_static_lifetime=true; + return array_symbol.symbol_expr(); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::declare_function + + Inputs: a name and a type + + Purpose: declare a function with the given name and type + +\*******************************************************************/ + +void string_refine_preprocesst::declare_function( + irep_idt function_name, const typet &type) +{ + auxiliary_symbolt func_symbol; + func_symbol.base_name=function_name; + func_symbol.is_static_lifetime=false; + func_symbol.mode=ID_java; + func_symbol.name=function_name; + func_symbol.type=type; + symbol_table.add(func_symbol); + goto_functions.function_map[function_name]; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::get_data_and_length_type_of_string + + Inputs: an expression, a reference to a data type and a reference to a + length type + + Purpose: assuming the expression is a java string, figure out what + the types for length and data are and put them into the references + given as argument + +\*******************************************************************/ + +void string_refine_preprocesst::get_data_and_length_type_of_string( + const exprt &expr, typet &data_type, typet &length_type) +{ + assert(refined_string_typet::is_java_string_type(expr.type()) || + refined_string_typet::is_java_string_builder_type(expr.type())); + typet object_type=ns.follow(expr.type()); + const struct_typet &struct_type=to_struct_type(object_type); + for(const auto &component : struct_type.components()) + if(component.get_name()=="length") + length_type=component.type(); + else if(component.get_name()=="data") + data_type=component.type(); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::make_cprover_string_assign + + Inputs: a goto_program, a position in this program, an expression and a + location + + Outputs: an expression + + Purpose: Introduce a temporary variable for cprover strings; + returns the cprover_string corresponding to rhs if it is a string + pointer and the original rhs otherwise. + +\*******************************************************************/ + +exprt string_refine_preprocesst::make_cprover_string_assign( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &rhs, + const source_locationt &location) +{ + if(refined_string_typet::is_java_string_pointer_type(rhs.type())) + { + auto pair=java_to_cprover_strings.insert( + std::pair(rhs, nil_exprt())); + + if(pair.second) + { + // We do the following assignments: + // cprover_string_array = *(rhs->data) + // cprover_string = { rhs->length; cprover_string_array } + + dereference_exprt deref(rhs, rhs.type().subtype()); + + typet data_type, length_type; + get_data_and_length_type_of_string(deref, data_type, length_type); + member_exprt length(deref, "length", length_type); + symbol_exprt array_lhs=fresh_array(data_type.subtype(), location); + + // string expression for the rhs of the second assignment + string_exprt new_rhs( + length, array_lhs, refined_string_typet(length_type, data_type)); + + member_exprt data(deref, "data", data_type); + dereference_exprt deref_data(data, data_type.subtype()); + symbol_exprt lhs=fresh_string(new_rhs.type(), location); + + std::list assignments; + assignments.emplace_back(array_lhs, deref_data); + assignments.emplace_back(lhs, new_rhs); + insert_assignments( + goto_program, target, target->function, location, assignments); + target=goto_program.insert_after(target); + pair.first->second=lhs; + } + return pair.first->second; + } + else if(rhs.id()==ID_typecast && + refined_string_typet::is_java_string_pointer_type(rhs.op0().type())) + { + exprt new_rhs=make_cprover_string_assign( + goto_program, target, rhs.op0(), location); + return typecast_exprt(new_rhs, rhs.type()); + } + else + return rhs; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::make_normal_assign + + Inputs: a goto_program, a position in this program, an expression lhs, + a function type, a function name, a vector of arguments, a location + and a signature + + Purpose: replace the current instruction by: + > lhs=function_name(arguments) : return_type @ location + If given, signature can force String conversion of given arguments. + The convention for signature is one character by argument + and 'S' denotes string. + +\*******************************************************************/ + +void string_refine_preprocesst::make_normal_assign( + goto_programt &goto_program, + goto_programt::targett target, + const exprt &lhs, + const code_typet &function_type, + const irep_idt &function_name, + const exprt::operandst &arguments, + const source_locationt &location, + const std::string &signature) +{ + if(function_name==ID_cprover_string_copy_func) + { + assert(!arguments.empty()); + make_string_copy(goto_program, target, lhs, arguments[0], location); + } + else + { + function_application_exprt rhs( + symbol_exprt(function_name), function_type.return_type()); + rhs.add_source_location()=location; + declare_function(function_name, function_type); + + exprt::operandst processed_arguments=process_arguments( + goto_program, target, arguments, location, signature); + rhs.arguments()=processed_arguments; + + code_assignt assignment(lhs, rhs); + assignment.add_source_location()=location; + target->make_assignment(); + target->code=assignment; + } +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::insert_assignments + + Inputs: a goto_program, a position in this program, a list of assignments + + Purpose: add the assignments to the program in the order they are given + +\*******************************************************************/ + +void string_refine_preprocesst::insert_assignments( + goto_programt &goto_program, + goto_programt::targett &target, + irep_idt function, + source_locationt location, + const std::list &va) +{ + if(va.empty()) + return; + + auto i=va.begin(); + target->make_assignment(); + target->code=*i; + target->function=function; + target->source_location=location; + for(i++; i!=va.end(); i++) + { + target=goto_program.insert_after(target); + target->make_assignment(); + target->code=*i; + target->function=function; + target->source_location=location; + } +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::make_string_assign + + Inputs: a goto_program, a position in this program, an expression lhs, + a function type, a function name, a vector of arguments, a location + and a signature + + Purpose: replace the current instruction by: + > lhs=malloc(String *) + > lhs->length=function_name_length(arguments) + > tmp_data=function_name_data(arguments) + > lhs->data=&tmp_data + +\*******************************************************************/ + +void string_refine_preprocesst::make_string_assign( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &lhs, + const code_typet &function_type, + const irep_idt &function_name, + const exprt::operandst &arguments, + const source_locationt &location, + const std::string &signature) +{ + assert(refined_string_typet::is_java_string_pointer_type( + function_type.return_type())); + dereference_exprt deref(lhs, lhs.type().subtype()); + typet object_type=ns.follow(deref.type()); + exprt object_size=size_of_expr(object_type, ns); + typet length_type, data_type; + get_data_and_length_type_of_string(deref, data_type, length_type); + + std::string fnamel=id2string(function_name)+"_length"; + std::string fnamed=id2string(function_name)+"_data"; + declare_function(fnamel, length_type); + declare_function(fnamed, data_type); + function_application_exprt rhs_length(symbol_exprt(fnamel), length_type); + function_application_exprt rhs_data( + symbol_exprt(fnamed), data_type.subtype()); + + exprt::operandst processed_arguments=process_arguments( + goto_program, target, arguments, location, signature); + rhs_length.arguments()=processed_arguments; + rhs_data.arguments()=processed_arguments; + + symbolt sym_length=get_fresh_aux_symbol( + length_type, "length", "length", location, ID_java, symbol_table); + symbol_exprt tmp_length=sym_length.symbol_expr(); + symbol_exprt tmp_array=fresh_array(data_type.subtype(), location); + member_exprt lhs_length(deref, "length", length_type); + member_exprt lhs_data(deref, "data", tmp_array.type()); + + // lhs=malloc(String *) + assert(object_size.is_not_nil()); // got nil object_size + side_effect_exprt malloc_expr(ID_malloc); + malloc_expr.copy_to_operands(object_size); + malloc_expr.type()=pointer_typet(object_type); + malloc_expr.add_source_location()=location; + + std::list assigns; + assigns.emplace_back(lhs, malloc_expr); + assigns.emplace_back(tmp_length, rhs_length); + assigns.emplace_back(lhs_length, tmp_length); + assigns.emplace_back(tmp_array, rhs_data); + assigns.emplace_back(lhs_data, address_of_exprt(tmp_array)); + insert_assignments(goto_program, target, target->function, location, assigns); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::make_assign + + Inputs: a goto_program, a position in this program, an expression lhs, + a function type, a function name, a vector of arguments, a location + and a signature + + Purpose: assign the result of the function application to lhs, + in case the function type is string, it does a special assignment + using `make_string_assign` + +\*******************************************************************/ + +void string_refine_preprocesst::make_assign( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &lhs, + const code_typet &function_type, + const irep_idt &function_name, + const exprt::operandst &arg, + const source_locationt &loc, + const std::string &sig) +{ + if(refined_string_typet::is_java_string_pointer_type( + function_type.return_type())) + make_string_assign( + goto_program, target, lhs, function_type, function_name, arg, loc, sig); + else + make_normal_assign( + goto_program, target, lhs, function_type, function_name, arg, loc, sig); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::make_string_copy + + Inputs: a goto_program, a position in this program, a lhs expression, + an argument expression and a location + + Outputs: an expression + + Purpose: replace the current instruction by: + > lhs->length=argument->length + > tmp_data=*(argument->data) + > lhs->data=&tmp_data + +\*******************************************************************/ + +void string_refine_preprocesst::make_string_copy( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &lhs, + const exprt &argument, + const source_locationt &location) +{ + // TODO : treat CharSequence and StringBuffer + assert(refined_string_typet::is_java_string_pointer_type(lhs.type()) || + refined_string_typet::is_java_string_builder_pointer_type(lhs.type())); + exprt deref=dereference_exprt(lhs, lhs.type().subtype()); + + typet length_type, data_type; + get_data_and_length_type_of_string(deref, data_type, length_type); + + dereference_exprt deref_arg(argument, argument.type().subtype()); + std::list assignments; + + exprt lhs_length=get_length(deref, length_type); + exprt rhs_length=get_length(deref_arg, length_type); + assignments.emplace_back(lhs_length, rhs_length); + + symbol_exprt tmp_data=fresh_array(data_type.subtype(), location); + exprt rhs_data=get_data(deref_arg, data_type); + exprt lhs_data=get_data(deref, data_type); + assignments.emplace_back( + tmp_data, dereference_exprt(rhs_data, data_type.subtype())); + assignments.emplace_back(lhs_data, address_of_exprt(tmp_data)); + + insert_assignments( + goto_program, target, target->function, location, assignments); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::make_string_function + + Inputs: a position in a goto program, a function name, an expression lhs, + a function type, name, arguments, a location and a signature string + + Purpose: at the current position replace `lhs=s.some_function(x,...)` + by `lhs=function_name(s,x,...)`; + +\*******************************************************************/ + +void string_refine_preprocesst::make_string_function( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &lhs, + const code_typet &function_type, + const irep_idt &function_name, + const exprt::operandst &arguments, + const source_locationt &location, + const std::string &signature) +{ + if(refined_string_typet::is_java_string_pointer_type( + function_type.return_type())) + make_string_assign( + goto_program, + target, + lhs, + function_type, + function_name, + arguments, + location, + signature); + else + make_normal_assign( + goto_program, + target, + lhs, + function_type, + function_name, + arguments, + location, + signature); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::make_string_function + + Inputs: a position in a goto program, a function name and two Boolean options + + Purpose: at the current position replace `lhs=s.some_function(x,...)` + by `lhs=function_name(s,x,...)`; + option `assign_first_arg` uses `s` instead of `lhs` in the resulting + expression; + option `skip_first_arg`, removes `s` from the arguments, ie `x` is + the first one + +\*******************************************************************/ + +void string_refine_preprocesst::make_string_function( + goto_programt &goto_program, + goto_programt::targett &target, + const irep_idt &function_name, + const std::string &signature, + bool assign_first_arg, + bool skip_first_arg) +{ + code_function_callt &function_call=to_code_function_call(target->code); + code_typet function_type=to_code_type(function_call.function().type()); + code_typet new_type; + const source_locationt &loc=function_call.source_location(); + declare_function(function_name, function_type); + function_application_exprt rhs; + std::vector args; + if(assign_first_arg) + { + assert(!function_call.arguments().empty()); + rhs.type()=function_call.arguments()[0].type(); + } + else + rhs.type()=function_type.return_type(); + rhs.add_source_location()=function_call.source_location(); + rhs.function()=symbol_exprt(function_name); + + std::size_t start_index=skip_first_arg?1:0; + for(std::size_t i=start_index; icode); + assert(!function_call.arguments().empty()); + string_builders[function_call.lhs()]=function_call.arguments()[0]; + make_string_function( + goto_program, target, function_name, signature, true, false); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::build_function_application + + Inputs: a function name, a type, a location and a vector of arguments + + Outputs: a function application expression + + Purpose: declare a function and construct an function application expression + with the given function name, type, location and arguments + +\*******************************************************************/ + +function_application_exprt + string_refine_preprocesst::build_function_application( + const irep_idt &function_name, + const typet &type, + const source_locationt &location, + const exprt::operandst &arguments) +{ + declare_function(function_name, type); + function_application_exprt function_app(symbol_exprt(function_name), type); + function_app.add_source_location()=location; + for(const auto &arg : arguments) + function_app.arguments().push_back(arg); + + return function_app; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::make_to_char_array_function + + Inputs: a goto program and a position in that goto program + + Purpose: at the given position replace `return_tmp0=s.toCharArray()` with: + > return_tmp0->data=&((s->data)[0]) + > return_tmp0->length=s->length + +\*******************************************************************/ + +void string_refine_preprocesst::make_to_char_array_function( + goto_programt &goto_program, goto_programt::targett &target) +{ + const code_function_callt &function_call=to_code_function_call(target->code); + + assert(!function_call.arguments().empty()); + const exprt &string_argument=function_call.arguments()[0]; + assert(refined_string_typet::is_java_string_pointer_type( + string_argument.type())); + + dereference_exprt deref(string_argument, string_argument.type().subtype()); + typet length_type, data_type; + get_data_and_length_type_of_string(deref, data_type, length_type); + std::list assignments; + + // &((s->data)[0]) + exprt rhs_data=get_data(deref, data_type); + dereference_exprt rhs_array(rhs_data, data_type.subtype()); + exprt first_index=from_integer(0, java_int_type()); + index_exprt first_element(rhs_array, first_index, java_char_type()); + address_of_exprt rhs_pointer(first_element); + + // return_tmp0->data=&((s->data)[0]) + typet deref_type=function_call.lhs().type().subtype(); + dereference_exprt deref_lhs(function_call.lhs(), deref_type); + exprt lhs_data=get_data(deref_lhs, data_type); + assignments.emplace_back(lhs_data, rhs_pointer); + + // return_tmp0->length=s->length + exprt rhs_length=get_length(deref, length_type); + exprt lhs_length=get_length(deref_lhs, length_type); + assignments.emplace_back(lhs_length, rhs_length); + source_locationt location=target->source_location; + insert_assignments( + goto_program, target, target->function, location, assignments); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::make_cprover_char_array_assign + + Inputs: a goto_program, a position in this program, an expression and a + location + + Outputs: a char array expression (not a pointer) + + Purpose: Introduce a temporary variable for cprover strings; + returns the cprover_string corresponding to rhs + +\*******************************************************************/ + +exprt string_refine_preprocesst::make_cprover_char_array_assign( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &rhs, + const source_locationt &location) +{ + // TODO : add an assertion on the type of rhs + + // We do the following assignments: + // cprover_string_array = rhs.data + // cprover_string = { rhs.length; cprover_string_array } + + // string expression for the rhs of the second assignment + string_exprt new_rhs(java_char_type()); + + typet data_type=new_rhs.content().type(); + typet length_type=java_int_type(); + + symbol_exprt array_lhs=fresh_array(data_type, location); + exprt array_rhs=get_data(rhs, new_rhs.content().type()); + symbol_exprt lhs=fresh_string(new_rhs.type(), location); + new_rhs.length()=get_length(rhs, length_type); + new_rhs.content()=array_lhs; + + std::list assignments; + assignments.emplace_back(array_lhs, array_rhs); + assignments.emplace_back(lhs, new_rhs); + insert_assignments( + goto_program, target, target->function, location, assignments); + target=goto_program.insert_after(target); + return lhs; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::make_char_array_function + + Inputs: a position in a goto program, a function name, two Boolean options, + and the index of the char array argument in the function + + Purpose: at the given position replace + `lhs=s.some_function(...,char_array,...)` by + > cprover_string = { char_array->length, *char_array } + > tmp_string=function_name(s, cprover_string, ...) + option `assign_first_arg` uses `s` instead of `lhs` in the second + assignment; + option `skip_first_arg`, removes `s` from the arguments, ie `x` is + the first one; + argument index gives the index of the argument containing char_array + +\*******************************************************************/ + +void string_refine_preprocesst::make_char_array_function( + goto_programt &goto_program, + goto_programt::targett &target, + const irep_idt &function_name, + const std::string &signature, + std::size_t index, + bool assign_first_arg, + bool skip_first_arg) +{ + code_function_callt &function_call=to_code_function_call(target->code); + code_typet function_type=to_code_type(function_call.function().type()); + code_typet new_function_type; + const source_locationt &location=function_call.source_location(); + assert(!function_call.arguments().size()>index); + const std::vector &args=function_call.arguments(); + std::vector new_args; + + exprt lhs; + if(assign_first_arg) + { + assert(!function_call.arguments().empty()); + lhs=function_call.arguments()[0]; + else + lhs=function_call.lhs(); + + if(lhs.id()==ID_typecast) + lhs=to_typecast_expr(lhs).op(); + + exprt char_array=dereference_exprt( + function_call.arguments()[index], + function_call.arguments()[index].type().subtype()); + exprt string=make_cprover_char_array_assign( + goto_program, target, char_array, location); + + std::size_t start_index=skip_first_arg?1:0; + for(std::size_t i=start_index; icode); + assert(!function_call.arguments().empty()); + string_builders[function_call.lhs()]=function_call.arguments()[0]; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::process_arguments + + Inputs: a goto program, a position, a list of expressions, a location and a + signature + + Outputs: a list of expressions + + Purpose: for each expression that is a string or that is at a position with + an 'S' character in the signature, we declare a new `cprover_string` + whose contents is deduced from the expression and replace the + expression by this cprover_string in the output list; + in the other case the expression is kept as is for the output list. + +\*******************************************************************/ + +exprt::operandst string_refine_preprocesst::process_arguments( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt::operandst &arguments, + const source_locationt &location, + const std::string &signature) +{ + exprt::operandst new_arguments; + + for(std::size_t i=0; isecond); + else + { + if(isecond; + else + return ""; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::replace_string_calls + + Inputs: a function in a goto_program + + Purpose: goes through the instructions, replace function calls to string + function by equivalent instructions using functions defined + for the string solver, replace string literals by string + expressions of the type used by the string solver + TODO: the current implementation is only for java functions, + we should add support for other languages + +\*******************************************************************/ + +void string_refine_preprocesst::replace_string_calls( + goto_functionst::function_mapt::iterator f_it) +{ + goto_programt &goto_program=f_it->second.body; + + Forall_goto_program_instructions(target, goto_program) + { + if(target->is_function_call()) + { + code_function_callt &function_call=to_code_function_call(target->code); + for(auto &arg : function_call.arguments()) + { + auto sb_it=string_builders.find(arg); + if(sb_it!=string_builders.end()) + arg=sb_it->second; + } + + if(function_call.function().id()==ID_symbol) + { + const irep_idt &function_id= + to_symbol_expr(function_call.function()).get_identifier(); + std::string signature=function_signature(function_id); + + auto it=string_functions.find(function_id); + if(it!=string_functions.end()) + make_string_function( + goto_program, target, it->second, signature, false, false); + + it=side_effect_functions.find(function_id); + if(it!=side_effect_functions.end()) + make_string_function_side_effect( + goto_program, target, it->second, signature); + + it=string_function_calls.find(function_id); + if(it!=string_function_calls.end()) + make_string_function_call( + goto_program, target, it->second, signature); + + it=string_of_char_array_functions.find(function_id); + if(it!=string_of_char_array_functions.end()) + make_char_array_function( + goto_program, target, it->second, signature, 0); + + it=string_of_char_array_function_calls.find(function_id); + if(it!=string_of_char_array_function_calls.end()) + make_char_array_function_call( + goto_program, target, it->second, signature); + + it=side_effect_char_array_functions.find(function_id); + if(it!=side_effect_char_array_functions.end()) + make_char_array_side_effect( + goto_program, target, it->second, signature); + + if(function_id==irep_idt("java::java.lang.String.toCharArray:()[C")) + make_to_char_array_function(goto_program, target); + } + } + else + { + if(target->is_assign()) + { + // In assignments we replace string literals and C string functions + code_assignt assignment=to_code_assign(target->code); + + exprt new_rhs=assignment.rhs(); + code_assignt new_assignment(assignment.lhs(), new_rhs); + + if(new_rhs.id()==ID_function_application) + { + function_application_exprt f=to_function_application_expr(new_rhs); + const exprt &name=f.function(); + assert(name.id()==ID_symbol); + const irep_idt &id=to_symbol_expr(name).get_identifier(); + auto it=c_string_functions.find(id); + if(it!=c_string_functions.end()) + { + declare_function(it->second, f.type()); + f.function()=symbol_exprt(it->second); + new_assignment=code_assignt(assignment.lhs(), f); + } + } + + new_assignment.add_source_location()=assignment.source_location(); + target->make_assignment(); + target->code=new_assignment; + } + } + } + return; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::initialize_string_function_table + + Purpose: fill maps with correspondance from java method names to cprover + functions + +\*******************************************************************/ + +void string_refine_preprocesst::initialize_string_function_table() +{ + string_functions["java::java.lang.String.codePointAt:(I)I"]= + ID_cprover_string_code_point_at_func; + string_functions["java::java.lang.String.codePointBefore:(I)I"]= + ID_cprover_string_code_point_before_func; + string_functions["java::java.lang.String.codePointCount:(II)I"]= + ID_cprover_string_code_point_count_func; + string_functions["java::java.lang.String.offsetByCodePoints:(II)I"]= + ID_cprover_string_offset_by_code_point_func; + string_functions["java::java.lang.String.hashCode:()I"]= + ID_cprover_string_hash_code_func; + string_functions["java::java.lang.String.indexOf:(I)I"]= + ID_cprover_string_index_of_func; + string_functions["java::java.lang.String.indexOf:(II)I"]= + ID_cprover_string_index_of_func; + string_functions["java::java.lang.String.indexOf:(Ljava/lang/String;)I"]= + ID_cprover_string_index_of_func; + string_functions["java::java.lang.String.indexOf:(Ljava/lang/String;I)I"]= + ID_cprover_string_index_of_func; + string_functions["java::java.lang.String.lastIndexOf:(I)I"]= + ID_cprover_string_last_index_of_func; + string_functions["java::java.lang.String.lastIndexOf:(II)I"]= + ID_cprover_string_last_index_of_func; + string_functions + ["java::java.lang.String.lastIndexOf:(Ljava/lang/String;)I"]= + ID_cprover_string_last_index_of_func; + string_functions + ["java::java.lang.String.lastIndexOf:(Ljava/lang/String;I)I"]= + ID_cprover_string_last_index_of_func; + string_functions + ["java::java.lang.String.concat:(Ljava/lang/String;)Ljava/lang/String;"]= + ID_cprover_string_concat_func; + string_functions["java::java.lang.String.length:()I"]= + ID_cprover_string_length_func; + string_functions["java::java.lang.StringBuilder.length:()I"]= + ID_cprover_string_length_func; + string_functions["java::java.lang.String.equals:(Ljava/lang/Object;)Z"]= + ID_cprover_string_equal_func; + string_functions + ["java::java.lang.String.equalsIgnoreCase:(Ljava/lang/String;)Z"]= + ID_cprover_string_equals_ignore_case_func; + string_functions["java::java.lang.String.startsWith:(Ljava/lang/String;)Z"]= + ID_cprover_string_startswith_func; + string_functions + ["java::java.lang.String.startsWith:(Ljava/lang/String;I)Z"]= + ID_cprover_string_startswith_func; + string_functions["java::java.lang.String.endsWith:(Ljava/lang/String;)Z"]= + ID_cprover_string_endswith_func; + string_functions["java::java.lang.String.substring:(II)Ljava/lang/String;"]= + ID_cprover_string_substring_func; + string_functions["java::java.lang.String.substring:(II)Ljava/lang/String;"]= + ID_cprover_string_substring_func; + string_functions["java::java.lang.String.substring:(I)Ljava/lang/String;"]= + ID_cprover_string_substring_func; + string_functions + ["java::java.lang.StringBuilder.substring:(II)Ljava/lang/String;"]= + ID_cprover_string_substring_func; + string_functions + ["java::java.lang.StringBuilder.substring:(I)Ljava/lang/String;"]= + ID_cprover_string_substring_func; + string_functions + ["java::java.lang.String.subSequence:(II)Ljava/lang/CharSequence;"]= + ID_cprover_string_substring_func; + string_functions["java::java.lang.String.trim:()Ljava/lang/String;"]= + ID_cprover_string_trim_func; + string_functions["java::java.lang.String.toLowerCase:()Ljava/lang/String;"]= + ID_cprover_string_to_lower_case_func; + string_functions["java::java.lang.String.toUpperCase:()Ljava/lang/String;"]= + ID_cprover_string_to_upper_case_func; + string_functions["java::java.lang.String.replace:(CC)Ljava/lang/String;"]= + ID_cprover_string_replace_func; + string_functions + ["java::java.lang.String.contains:(Ljava/lang/CharSequence;)Z"]= + ID_cprover_string_contains_func; + string_functions["java::java.lang.String.compareTo:(Ljava/lang/String;)I"]= + ID_cprover_string_compare_to_func; + string_functions["java::java.lang.String.intern:()Ljava/lang/String;"]= + ID_cprover_string_intern_func; + string_functions["java::java.lang.String.isEmpty:()Z"]= + ID_cprover_string_is_empty_func; + string_functions["java::java.lang.String.charAt:(I)C"]= + ID_cprover_string_char_at_func; + string_functions["java::java.lang.StringBuilder.charAt:(I)C"]= + ID_cprover_string_char_at_func; + string_functions["java::java.lang.CharSequence.charAt:(I)C"]= + ID_cprover_string_char_at_func; + string_functions + ["java::java.lang.StringBuilder.toString:()Ljava/lang/String;"]= + ID_cprover_string_copy_func; + + string_functions["java::java.lang.String.valueOf:(F)Ljava/lang/String;"]= + ID_cprover_string_of_float_func; + string_functions["java::java.lang.Float.toString:(F)Ljava/lang/String;"]= + ID_cprover_string_of_float_func; + string_functions["java::java.lang.Integer.toString:(I)Ljava/lang/String;"]= + ID_cprover_string_of_int_func; + string_functions["java::java.lang.String.valueOf:(I)Ljava/lang/String;"]= + ID_cprover_string_of_int_func; + string_functions["java::java.lang.Integer.toHexString:(I)Ljava/lang/String;"]= + ID_cprover_string_of_int_hex_func; + string_functions["java::java.lang.String.valueOf:(L)Ljava/lang/String;"]= + ID_cprover_string_of_long_func; + string_functions["java::java.lang.String.valueOf:(D)Ljava/lang/String;"]= + ID_cprover_string_of_double_func; + string_functions["java::java.lang.String.valueOf:(Z)Ljava/lang/String;"]= + ID_cprover_string_of_bool_func; + string_functions["java::java.lang.String.valueOf:(C)Ljava/lang/String;"]= + ID_cprover_string_of_char_func; + string_functions["java::java.lang.Integer.parseInt:(Ljava/lang/String;)I"]= + ID_cprover_string_parse_int_func; + + side_effect_functions + ["java::java.lang.StringBuilder.append:(Ljava/lang/String;)" + "Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_func; + side_effect_functions["java::java.lang.StringBuilder.setCharAt:(IC)V"]= + ID_cprover_string_char_set_func; + side_effect_functions + ["java::java.lang.StringBuilder.append:(I)Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_int_func; + side_effect_functions + ["java::java.lang.StringBuilder.append:(J)Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_long_func; + side_effect_functions + ["java::java.lang.StringBuilder.append:(Z)Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_bool_func; + side_effect_functions + ["java::java.lang.StringBuilder.append:(C)Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_char_func; + side_effect_functions + ["java::java.lang.StringBuilder.append:(D)Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_double_func; + side_effect_functions + ["java::java.lang.StringBuilder.append:(F)Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_float_func; + side_effect_functions + ["java::java.lang.StringBuilder.appendCodePoint:(I)" + "Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_code_point_func; + side_effect_functions + ["java::java.lang.StringBuilder.delete:(II)Ljava/lang/StringBuilder;"]= + ID_cprover_string_delete_func; + side_effect_functions + ["java::java.lang.StringBuilder.deleteCharAt:(I)Ljava/lang/StringBuilder;"]= + ID_cprover_string_delete_char_at_func; + side_effect_functions + ["java::java.lang.StringBuilder.insert:(ILjava/lang/String;)" + "Ljava/lang/StringBuilder;"]= + ID_cprover_string_insert_func; + side_effect_functions + ["java::java.lang.StringBuilder.insert:(II)Ljava/lang/StringBuilder;"]= + ID_cprover_string_insert_int_func; + side_effect_functions + ["java::java.lang.StringBuilder.insert:(IJ)Ljava/lang/StringBuilder;"]= + ID_cprover_string_insert_long_func; + side_effect_functions + ["java::java.lang.StringBuilder.insert:(IC)Ljava/lang/StringBuilder;"]= + ID_cprover_string_insert_char_func; + side_effect_functions + ["java::java.lang.StringBuilder.insert:(IZ)Ljava/lang/StringBuilder;"]= + ID_cprover_string_insert_bool_func; + side_effect_functions + ["java::java.lang.StringBuilder.setLength:(I)V"]= + ID_cprover_string_set_length_func; + + + side_effect_char_array_functions + ["java::java.lang.StringBuilder.insert:(I[CII)Ljava/lang/StringBuilder;"]= + ID_cprover_string_insert_char_array_func; + side_effect_char_array_functions + ["java::java.lang.StringBuilder.insert:(I[C)Ljava/lang/StringBuilder;"]= + ID_cprover_string_insert_char_array_func; + + string_function_calls + ["java::java.lang.String.:(Ljava/lang/String;)V"]= + ID_cprover_string_copy_func; + string_function_calls + ["java::java.lang.String.:(Ljava/lang/StringBuilder;)V"]= + ID_cprover_string_copy_func; + string_function_calls + ["java::java.lang.StringBuilder.:(Ljava/lang/String;)V"]= + ID_cprover_string_copy_func; + string_function_calls["java::java.lang.String.:()V"]= + ID_cprover_string_empty_string_func; + string_function_calls["java::java.lang.StringBuilder.:()V"]= + ID_cprover_string_empty_string_func; + + string_of_char_array_function_calls["java::java.lang.String.:([C)V"]= + ID_cprover_string_of_char_array_func; + string_of_char_array_function_calls["java::java.lang.String.:([CII)V"]= + ID_cprover_string_of_char_array_func; + + string_of_char_array_functions + ["java::java.lang.String.valueOf:([CII)Ljava/lang/String;"]= + ID_cprover_string_of_char_array_func; + string_of_char_array_functions + ["java::java.lang.String.valueOf:([C)Ljava/lang/String;"]= + ID_cprover_string_of_char_array_func; + string_of_char_array_functions + ["java::java.lang.String.copyValueOf:([CII)Ljava/lang/String;"]= + ID_cprover_string_of_char_array_func; + string_of_char_array_functions + ["java::java.lang.String.copyValueOf:([C)Ljava/lang/String;"]= + ID_cprover_string_of_char_array_func; + + c_string_functions["__CPROVER_uninterpreted_string_literal_func"]= + ID_cprover_string_literal_func; + c_string_functions["__CPROVER_uninterpreted_string_char_at_func"]= + ID_cprover_string_char_at_func; + c_string_functions["__CPROVER_uninterpreted_string_equal_func"]= + ID_cprover_string_equal_func; + c_string_functions["__CPROVER_uninterpreted_string_concat_func"]= + ID_cprover_string_concat_func; + c_string_functions["__CPROVER_uninterpreted_string_length_func"]= + ID_cprover_string_length_func; + c_string_functions["__CPROVER_uninterpreted_string_substring_func"]= + ID_cprover_string_substring_func; + c_string_functions["__CPROVER_uninterpreted_string_is_prefix_func"]= + ID_cprover_string_is_prefix_func; + c_string_functions["__CPROVER_uninterpreted_string_is_suffix_func"]= + ID_cprover_string_is_suffix_func; + c_string_functions["__CPROVER_uninterpreted_string_contains_func"]= + ID_cprover_string_contains_func; + c_string_functions["__CPROVER_uninterpreted_string_index_of_func"]= + ID_cprover_string_index_of_func; + c_string_functions["__CPROVER_uninterpreted_string_last_index_of_func"]= + ID_cprover_string_last_index_of_func; + c_string_functions["__CPROVER_uninterpreted_string_char_set_func"]= + ID_cprover_string_char_set_func; + c_string_functions["__CPROVER_uninterpreted_string_copy_func"]= + ID_cprover_string_copy_func; + c_string_functions["__CPROVER_uninterpreted_string_parse_int_func"]= + ID_cprover_string_parse_int_func; + c_string_functions["__CPROVER_uninterpreted_string_of_int_func"]= + ID_cprover_string_of_int_func; + + signatures["java::java.lang.String.equals:(Ljava/lang/Object;)Z"]="SSZ"; + signatures + ["java::java.lang.String.contains:(Ljava/lang/CharSequence;)Z"]= + "SSZ"; +} + +/*******************************************************************\ + +Constructor: string_refine_preprocesst::string_refine_preprocesst + + Inputs: a symbol table, goto functions, a message handler + + Purpose: process the goto function by replacing calls to string functions + +\*******************************************************************/ + +string_refine_preprocesst::string_refine_preprocesst( + symbol_tablet &_symbol_table, + goto_functionst &_goto_functions, + message_handlert &_message_handler): + messaget(_message_handler), + ns(_symbol_table), + symbol_table(_symbol_table), + goto_functions(_goto_functions), + next_symbol_id(0), + jls_ptr(symbol_typet("java::java.lang.String")) +{ + initialize_string_function_table(); + Forall_goto_functions(it, goto_functions) + replace_string_calls(it); +} diff --git a/src/goto-programs/string_refine_preprocess.h b/src/goto-programs/string_refine_preprocess.h new file mode 100644 index 00000000000..37e178f799a --- /dev/null +++ b/src/goto-programs/string_refine_preprocess.h @@ -0,0 +1,215 @@ +/*******************************************************************\ + +Module: Preprocess a goto-programs so that calls to the java String + library are recognized by the PASS algorithm + +Author: Romain Brenguier + +Date: September 2016 + +\*******************************************************************/ + +#ifndef CPROVER_GOTO_PROGRAMS_STRING_REFINE_PREPROCESS_H +#define CPROVER_GOTO_PROGRAMS_STRING_REFINE_PREPROCESS_H + +#include +#include + +class string_refine_preprocesst:public messaget +{ + public: + string_refine_preprocesst( + symbol_tablet &, goto_functionst &, message_handlert &); + + private: + namespacet ns; + symbol_tablet & symbol_table; + goto_functionst & goto_functions; + + typedef std::unordered_map id_mapt; + typedef std::unordered_map expr_mapt; + + // String builders maps the different names of a same StringBuilder object + // to a unique expression. + expr_mapt string_builders; + + // Map name of Java string functions to there equivalent in the solver + id_mapt side_effect_functions; + id_mapt string_functions; + id_mapt c_string_functions; + id_mapt string_function_calls; + id_mapt string_of_char_array_functions; + id_mapt string_of_char_array_function_calls; + id_mapt side_effect_char_array_functions; + + std::unordered_map signatures; + expr_mapt hidden_strings; + expr_mapt java_to_cprover_strings; + + // unique id for each newly created symbols + int next_symbol_id; + + void initialize_string_function_table(); + + symbol_exprt fresh_array( + const typet &type, const source_locationt &location); + symbol_exprt fresh_string( + const typet &type, const source_locationt &location); + + // get the data member of a java string + static exprt get_data(const exprt &string, const typet &data_type) + { + return member_exprt(string, "data", data_type); + } + + // get the length member of a java string + exprt get_length(const exprt &string, const typet &length_type) + { + return member_exprt(string, "length", length_type); + } + + // type of pointers to string + pointer_typet jls_ptr; + exprt replace_string(const exprt &in); + exprt replace_string_in_assign(const exprt &in); + + void insert_assignments( + goto_programt &goto_program, + goto_programt::targett &target, + irep_idt function, + source_locationt location, + const std::list &va); + + exprt replace_string_pointer(const exprt &in); + + // Replace string builders by expression of the mapping and make + // assignments for strings as string_exprt + exprt::operandst process_arguments( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt::operandst &arguments, + const source_locationt &location, + const std::string &signature=""); + + // Signature of the named function if it is defined in the signature map, + // empty string otherwise + std::string function_signature(const irep_idt &function_id); + + void declare_function(irep_idt function_name, const typet &type); + + void get_data_and_length_type_of_string( + const exprt &expr, typet &data_type, typet &length_type); + + function_application_exprt build_function_application( + const irep_idt &function_name, + const typet &type, + const source_locationt &location, + const exprt::operandst &arguments); + + void make_normal_assign( + goto_programt &goto_program, + goto_programt::targett target, + const exprt &lhs, + const code_typet &function_type, + const irep_idt &function_name, + const exprt::operandst &arguments, + const source_locationt &location, + const std::string &signature=""); + + void make_string_assign( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &lhs, + const code_typet &function_type, + const irep_idt &function_name, + const exprt::operandst &arguments, + const source_locationt &location, + const std::string &signature); + + void make_assign( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &lhs, + const code_typet &function_type, + const irep_idt &function_name, + const exprt::operandst &arg, + const source_locationt &loc, + const std::string &sig); + + exprt make_cprover_string_assign( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &rhs, + const source_locationt &location); + + void make_string_copy( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &lhs, + const exprt &argument, + const source_locationt &location); + + void make_string_function( + goto_programt &goto_program, + goto_programt::targett &target, + const irep_idt &function_name, + const std::string &signature, + bool assign_first_arg=false, + bool skip_first_arg=false); + + void make_string_function( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &lhs, + const code_typet &function_type, + const irep_idt &function_name, + const exprt::operandst &arguments, + const source_locationt &location, + const std::string &signature); + + void make_string_function_call( + goto_programt &goto_program, + goto_programt::targett &target, + const irep_idt &function_name, + const std::string &signature); + + void make_string_function_side_effect( + goto_programt &goto_program, + goto_programt::targett &target, + const irep_idt &function_name, + const std::string &signature); + + void make_to_char_array_function( + goto_programt &goto_program, goto_programt::targett &); + + exprt make_cprover_char_array_assign( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &rhs, + const source_locationt &location); + + void make_char_array_function( + goto_programt &goto_program, + goto_programt::targett &target, + const irep_idt &function_name, + const std::string &signature, + std::size_t index, + bool assign_first_arg=false, + bool skip_first_arg=false); + + void make_char_array_function_call( + goto_programt &goto_program, + goto_programt::targett &target, + const irep_idt &function_name, + const std::string &signature); + + void make_char_array_side_effect( + goto_programt &goto_program, + goto_programt::targett &target, + const irep_idt &function_name, + const std::string &signature); + + void replace_string_calls(goto_functionst::function_mapt::iterator f_it); +}; + +#endif diff --git a/src/util/std_expr.h b/src/util/std_expr.h index a2f78ab25e8..5c5856b4a9d 100644 --- a/src/util/std_expr.h +++ b/src/util/std_expr.h @@ -3450,6 +3450,19 @@ class function_application_exprt:public exprt operands().resize(2); } + explicit function_application_exprt(const typet &_type): + exprt(ID_function_application, _type) + { + operands().resize(2); + } + + function_application_exprt( + const symbol_exprt &_function, const typet &_type): + function_application_exprt(_type) // NOLINT(runtime/explicit) + { + function()=_function; + } + exprt &function() { return op0(); From 3a2e210d482e568f6114108ce28bf14aa43569ab Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Fri, 17 Feb 2017 13:10:40 +0000 Subject: [PATCH 129/699] Moving is_java_string_type functions to string_preprocess This avoid dependencies between goto-programs and solver. We also removed function is_unrefined_string_type which should not be needed in the string solver. Removed also mention of java string types and unrefined types in the solver. These mentions should not be necessary, since we are not supposed to do anything java specific. The solver should only have to deal with refined string types and possibly char arrays. --- .../string_refine_preprocess.cpp | 146 ++++++++++++++++-- src/goto-programs/string_refine_preprocess.h | 10 ++ .../refinement/refined_string_type.cpp | 95 ------------ src/solvers/refinement/refined_string_type.h | 36 +---- .../string_constraint_generator_constants.cpp | 2 +- .../string_constraint_generator_indexof.cpp | 20 ++- .../string_constraint_generator_main.cpp | 4 +- src/solvers/refinement/string_refinement.cpp | 6 +- 8 files changed, 166 insertions(+), 153 deletions(-) diff --git a/src/goto-programs/string_refine_preprocess.cpp b/src/goto-programs/string_refine_preprocess.cpp index c4dc1a92960..b14153c26c1 100644 --- a/src/goto-programs/string_refine_preprocess.cpp +++ b/src/goto-programs/string_refine_preprocess.cpp @@ -22,7 +22,125 @@ Date: September 2016 #include "string_refine_preprocess.h" -/******************************************************************* \ +/*******************************************************************\ + +Function: string_refine_preprocesst::is_java_string_pointer_type + + Inputs: a type + + Outputs: Boolean telling whether the type is that of java string pointers + +\*******************************************************************/ + +bool string_refine_preprocesst::is_java_string_pointer_type(const typet &type) +{ + if(type.id()==ID_pointer) + { + const pointer_typet &pt=to_pointer_type(type); + const typet &subtype=pt.subtype(); + return is_java_string_type(subtype); + } + return false; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::is_java_string_type + + Inputs: a type + + Outputs: Boolean telling whether the type is that of java string + +\*******************************************************************/ + +bool string_refine_preprocesst::is_java_string_type(const typet &type) +{ + if(type.id()==ID_symbol) + { + const irep_idt &tag=to_symbol_type(type).get_identifier(); + return tag=="java::java.lang.String"; + } + else if(type.id()==ID_struct) + { + const irep_idt &tag=to_struct_type(type).get_tag(); + return tag=="java.lang.String"; + } + return false; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::is_java_string_builder_type + + Inputs: a type + + Outputs: Boolean telling whether the type is that of java string builder + +\*******************************************************************/ + +bool string_refine_preprocesst::is_java_string_builder_type(const typet &type) +{ + if(type.id()==ID_pointer) + { + const pointer_typet &pt=to_pointer_type(type); + const typet &subtype=pt.subtype(); + if(subtype.id()==ID_struct) + { + const irep_idt &tag=to_struct_type(subtype).get_tag(); + return tag=="java.lang.StringBuilder"; + } + } + return false; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::is_java_string_builder_pointer_type + + Inputs: a type + + Outputs: Boolean telling whether the type is that of java StringBuilder + pointers + +\*******************************************************************/ + +bool string_refine_preprocesst::is_java_string_builder_pointer_type( + const typet &type) +{ + if(type.id()==ID_pointer) + { + const pointer_typet &pt=to_pointer_type(type); + const typet &subtype=pt.subtype(); + return is_java_string_builder_type(subtype); + } + return false; +} +/*******************************************************************\ + +Function: string_refine_preprocesst::is_java_char_sequence_type + + Inputs: a type + + Outputs: Boolean telling whether the type is that of java char sequence + +\*******************************************************************/ + +bool string_refine_preprocesst::is_java_char_sequence_type(const typet &type) +{ + if(type.id()==ID_pointer) + { + const pointer_typet &pt=to_pointer_type(type); + const typet &subtype=pt.subtype(); + if(subtype.id()==ID_struct) + { + const irep_idt &tag=to_struct_type(subtype).get_tag(); + return tag=="java.lang.CharSequence"; + } + } + return false; +} + +/*******************************************************************\ Function: string_refine_preprocesst::fresh_array @@ -114,8 +232,8 @@ Function: string_refine_preprocesst::get_data_and_length_type_of_string void string_refine_preprocesst::get_data_and_length_type_of_string( const exprt &expr, typet &data_type, typet &length_type) { - assert(refined_string_typet::is_java_string_type(expr.type()) || - refined_string_typet::is_java_string_builder_type(expr.type())); + assert(is_java_string_type(expr.type()) || + is_java_string_builder_type(expr.type())); typet object_type=ns.follow(expr.type()); const struct_typet &struct_type=to_struct_type(object_type); for(const auto &component : struct_type.components()) @@ -146,7 +264,7 @@ exprt string_refine_preprocesst::make_cprover_string_assign( const exprt &rhs, const source_locationt &location) { - if(refined_string_typet::is_java_string_pointer_type(rhs.type())) + if(is_java_string_pointer_type(rhs.type())) { auto pair=java_to_cprover_strings.insert( std::pair(rhs, nil_exprt())); @@ -183,7 +301,7 @@ exprt string_refine_preprocesst::make_cprover_string_assign( return pair.first->second; } else if(rhs.id()==ID_typecast && - refined_string_typet::is_java_string_pointer_type(rhs.op0().type())) + is_java_string_pointer_type(rhs.op0().type())) { exprt new_rhs=make_cprover_string_assign( goto_program, target, rhs.op0(), location); @@ -303,8 +421,7 @@ void string_refine_preprocesst::make_string_assign( const source_locationt &location, const std::string &signature) { - assert(refined_string_typet::is_java_string_pointer_type( - function_type.return_type())); + assert(is_java_string_pointer_type(function_type.return_type())); dereference_exprt deref(lhs, lhs.type().subtype()); typet object_type=ns.follow(deref.type()); exprt object_size=size_of_expr(object_type, ns); @@ -371,8 +488,7 @@ void string_refine_preprocesst::make_assign( const source_locationt &loc, const std::string &sig) { - if(refined_string_typet::is_java_string_pointer_type( - function_type.return_type())) + if(is_java_string_pointer_type(function_type.return_type())) make_string_assign( goto_program, target, lhs, function_type, function_name, arg, loc, sig); else @@ -404,8 +520,8 @@ void string_refine_preprocesst::make_string_copy( const source_locationt &location) { // TODO : treat CharSequence and StringBuffer - assert(refined_string_typet::is_java_string_pointer_type(lhs.type()) || - refined_string_typet::is_java_string_builder_pointer_type(lhs.type())); + assert(is_java_string_pointer_type(lhs.type()) || + is_java_string_builder_pointer_type(lhs.type())); exprt deref=dereference_exprt(lhs, lhs.type().subtype()); typet length_type, data_type; @@ -451,8 +567,7 @@ void string_refine_preprocesst::make_string_function( const source_locationt &location, const std::string &signature) { - if(refined_string_typet::is_java_string_pointer_type( - function_type.return_type())) + if(is_java_string_pointer_type(function_type.return_type())) make_string_assign( goto_program, target, @@ -633,8 +748,7 @@ void string_refine_preprocesst::make_to_char_array_function( assert(!function_call.arguments().empty()); const exprt &string_argument=function_call.arguments()[0]; - assert(refined_string_typet::is_java_string_pointer_type( - string_argument.type())); + assert(is_java_string_pointer_type(string_argument.type())); dereference_exprt deref(string_argument, string_argument.type().subtype()); typet length_type, data_type; @@ -870,7 +984,7 @@ exprt::operandst string_refine_preprocesst::process_arguments( { while(arg.id()==ID_typecast) arg=arg.op0(); - if(!refined_string_typet::is_java_string_type(arg.type())) + if(!is_java_string_type(arg.type())) arg=typecast_exprt(arg, jls_ptr); } exprt arg2=make_cprover_string_assign( diff --git a/src/goto-programs/string_refine_preprocess.h b/src/goto-programs/string_refine_preprocess.h index 37e178f799a..613d0161926 100644 --- a/src/goto-programs/string_refine_preprocess.h +++ b/src/goto-programs/string_refine_preprocess.h @@ -51,6 +51,16 @@ class string_refine_preprocesst:public messaget void initialize_string_function_table(); + static bool is_java_string_pointer_type(const typet &type); + + static bool is_java_string_type(const typet &type); + + static bool is_java_string_builder_type(const typet &type); + + static bool is_java_string_builder_pointer_type(const typet &type); + + static bool is_java_char_sequence_type(const typet &type); + symbol_exprt fresh_array( const typet &type, const source_locationt &location); symbol_exprt fresh_string( diff --git a/src/solvers/refinement/refined_string_type.cpp b/src/solvers/refinement/refined_string_type.cpp index 012d30eb8de..3362c71e0db 100644 --- a/src/solvers/refinement/refined_string_type.cpp +++ b/src/solvers/refinement/refined_string_type.cpp @@ -48,98 +48,3 @@ bool refined_string_typet::is_c_string_type(const typet &type) to_struct_type(type).get_tag()==CPROVER_PREFIX"string"; } -/*******************************************************************\ - -Function: refined_string_typet::is_java_string_pointer_type - - Inputs: a type - - Outputs: Boolean telling whether the type is that of java string pointers - -\*******************************************************************/ - -bool refined_string_typet::is_java_string_pointer_type(const typet &type) -{ - if(type.id()==ID_pointer) - { - const pointer_typet &pt=to_pointer_type(type); - const typet &subtype=pt.subtype(); - return is_java_string_type(subtype); - } - return false; -} - -/*******************************************************************\ - -Function: refined_string_typet::is_java_string_type - - Inputs: a type - - Outputs: Boolean telling whether the type is that of java string - -\*******************************************************************/ - -bool refined_string_typet::is_java_string_type(const typet &type) -{ - if(type.id()==ID_symbol) - { - irep_idt tag=to_symbol_type(type).get_identifier(); - return tag=="java::java.lang.String"; - } - else if(type.id()==ID_struct) - { - irep_idt tag=to_struct_type(type).get_tag(); - return tag=="java.lang.String"; - } - return false; -} - -/*******************************************************************\ - -Function: refined_string_typet::is_java_string_builder_type - - Inputs: a type - - Outputs: Boolean telling whether the type is that of java string builder - -\*******************************************************************/ - -bool refined_string_typet::is_java_string_builder_type(const typet &type) -{ - if(type.id()==ID_pointer) - { - const pointer_typet &pt=to_pointer_type(type); - const typet &subtype=pt.subtype(); - if(subtype.id()==ID_struct) - { - irep_idt tag=to_struct_type(subtype).get_tag(); - return tag=="java.lang.StringBuilder"; - } - } - return false; -} - -/*******************************************************************\ - -Function: refined_string_typet::is_java_char_sequence_type - - Inputs: a type - - Outputs: Boolean telling whether the type is that of java char sequence - -\*******************************************************************/ - -bool refined_string_typet::is_java_char_sequence_type(const typet &type) -{ - if(type.id()==ID_pointer) - { - const pointer_typet &pt=to_pointer_type(type); - const typet &subtype=pt.subtype(); - if(subtype.id()==ID_struct) - { - const irep_idt &tag=to_struct_type(subtype).get_tag(); - return tag=="java.lang.CharSequence"; - } - } - return false; -} diff --git a/src/solvers/refinement/refined_string_type.h b/src/solvers/refinement/refined_string_type.h index 3ecc0ac3a9f..3b36b19e826 100644 --- a/src/solvers/refinement/refined_string_type.h +++ b/src/solvers/refinement/refined_string_type.h @@ -33,41 +33,20 @@ class refined_string_typet: public struct_typet const typet &get_char_type() const { - assert(components().size()==2); - return components()[0].type(); + return get_content_type().subtype(); } const typet &get_index_type() const { - return get_content_type().size().type(); + assert(components().size()==2); + return components()[0].type(); } - // For C the unrefined string type is __CPROVER_string, for java it is a - // pointer to a struct with tag java.lang.String + // For C the unrefined string type is __CPROVER_string static bool is_c_string_type(const typet &type); - static bool is_java_string_pointer_type(const typet &type); - - static bool is_java_string_type(const typet &type); - - static bool is_java_string_builder_type(const typet &type); - - static bool is_java_char_sequence_type(const typet &type); - - static bool is_unrefined_string_type(const typet &type) - { - return ( - is_c_string_type(type) || - is_java_string_pointer_type(type) || - is_java_string_builder_type(type) || - is_java_char_sequence_type(type)); - } - - static bool is_unrefined_string(const exprt &expr) - { - return (is_unrefined_string_type(expr.type())); - } + static bool is_refined_string_type(const typet &type); constant_exprt index_of_int(int i) const { @@ -75,9 +54,10 @@ class refined_string_typet: public struct_typet } }; -const refined_string_typet &to_refined_string_type(const typet &type) +extern inline const refined_string_typet &to_refined_string_type( + const typet &type) { - assert(type.id()==ID_struct); + assert(refined_string_typet::is_refined_string_type(type)); return static_cast(type); } diff --git a/src/solvers/refinement/string_constraint_generator_constants.cpp b/src/solvers/refinement/string_constraint_generator_constants.cpp index 90769747949..64ffabfd266 100644 --- a/src/solvers/refinement/string_constraint_generator_constants.cpp +++ b/src/solvers/refinement/string_constraint_generator_constants.cpp @@ -132,7 +132,7 @@ string_exprt string_constraint_generatort::add_axioms_from_literal( else { // Java string constant - assert(refined_string_typet::is_unrefined_string_type(arg.type())); + assert(arg.id()==ID_symbol); const exprt &s=arg.op0(); // It seems the value of the string is lost, diff --git a/src/solvers/refinement/string_constraint_generator_indexof.cpp b/src/solvers/refinement/string_constraint_generator_indexof.cpp index 93db048458b..283de683bd6 100644 --- a/src/solvers/refinement/string_constraint_generator_indexof.cpp +++ b/src/solvers/refinement/string_constraint_generator_indexof.cpp @@ -186,14 +186,16 @@ exprt string_constraint_generatort::add_axioms_for_index_of( else assert(false); - if(refined_string_typet::is_java_string_pointer_type(c.type())) + if(c.type().id()==ID_unsignedbv) + { + return add_axioms_for_index_of( + str, typecast_exprt(c, ref_type.get_char_type()), from_index); + } + else { string_exprt sub=add_axioms_for_string_expr(c); return add_axioms_for_index_of_string(str, sub, from_index); } - else - return add_axioms_for_index_of( - str, typecast_exprt(c, ref_type.get_char_type()), from_index); } exprt string_constraint_generatort::add_axioms_for_last_index_of( @@ -280,12 +282,14 @@ exprt string_constraint_generatort::add_axioms_for_last_index_of( else assert(false); - if(refined_string_typet::is_java_string_pointer_type(c.type())) + if(c.type().id()==ID_unsignedbv) + { + return add_axioms_for_last_index_of( + str, typecast_exprt(c, ref_type.get_char_type()), from_index); + } + else { string_exprt sub=add_axioms_for_string_expr(c); return add_axioms_for_last_index_of_string(str, sub, from_index); } - else - return add_axioms_for_last_index_of( - str, typecast_exprt(c, ref_type.get_char_type()), from_index); } diff --git a/src/solvers/refinement/string_constraint_generator_main.cpp b/src/solvers/refinement/string_constraint_generator_main.cpp index 5a269e5ad3b..0179a2fcb61 100644 --- a/src/solvers/refinement/string_constraint_generator_main.cpp +++ b/src/solvers/refinement/string_constraint_generator_main.cpp @@ -215,10 +215,10 @@ string_exprt string_constraint_generatort::add_axioms_for_if( const if_exprt &expr) { assert( - refined_string_typet::is_unrefined_string_type(expr.true_case().type())); + refined_string_typet::is_c_string_type(expr.true_case().type())); string_exprt t=add_axioms_for_string_expr(expr.true_case()); assert( - refined_string_typet::is_unrefined_string_type(expr.false_case().type())); + refined_string_typet::is_c_string_type(expr.false_case().type())); string_exprt f=add_axioms_for_string_expr(expr.false_case()); const refined_string_typet &ref_type=to_refined_string_type(t.type()); const typet &index_type=ref_type.get_index_type(); diff --git a/src/solvers/refinement/string_refinement.cpp b/src/solvers/refinement/string_refinement.cpp index 16b89bc43c8..db9a2c460cc 100644 --- a/src/solvers/refinement/string_refinement.cpp +++ b/src/solvers/refinement/string_refinement.cpp @@ -146,7 +146,7 @@ bvt string_refinementt::convert_symbol(const exprt &expr) const irep_idt &identifier=expr.get(ID_identifier); assert(!identifier.empty()); - if(refined_string_typet::is_unrefined_string_type(type)) + if(refined_string_typet::is_refined_string_type(type)) { string_exprt str= generator.find_or_add_string_of_symbol(to_symbol_expr(expr)); @@ -216,7 +216,7 @@ bool string_refinementt::boolbv_set_equality_to_true(const equal_exprt &expr) if(expr.rhs().id()==ID_typecast) { exprt uncast=to_typecast_expr(expr.rhs()).op(); - if(refined_string_typet::is_unrefined_string_type(uncast.type())) + if(refined_string_typet::is_refined_string_type(uncast.type())) { debug() << "(sr) detected casted string" << eom; symbol_exprt sym=to_symbol_expr(expr.lhs()); @@ -225,7 +225,7 @@ bool string_refinementt::boolbv_set_equality_to_true(const equal_exprt &expr) } } - if(refined_string_typet::is_unrefined_string_type(type)) + if(refined_string_typet::is_refined_string_type(type)) { symbol_exprt sym=to_symbol_expr(expr.lhs()); generator.set_string_symbol_equal_to_expr(sym, expr.rhs()); From 70af9ce6148e03ed7c2179642486651db06ff47f Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Fri, 24 Feb 2017 11:02:55 +0000 Subject: [PATCH 130/699] Moving refined_string_type to util This is a more appropriate location for this module since it's used both in the preprocessing of goto-programs and the string solver. --- src/goto-programs/string_refine_preprocess.cpp | 3 +-- src/solvers/refinement/string_constraint.h | 2 +- src/solvers/refinement/string_constraint_generator.h | 2 +- src/{solvers/refinement => util}/refined_string_type.cpp | 0 src/{solvers/refinement => util}/refined_string_type.h | 4 ++-- 5 files changed, 5 insertions(+), 6 deletions(-) rename src/{solvers/refinement => util}/refined_string_type.cpp (100%) rename src/{solvers/refinement => util}/refined_string_type.h (93%) diff --git a/src/goto-programs/string_refine_preprocess.cpp b/src/goto-programs/string_refine_preprocess.cpp index b14153c26c1..ec02988d577 100644 --- a/src/goto-programs/string_refine_preprocess.cpp +++ b/src/goto-programs/string_refine_preprocess.cpp @@ -14,10 +14,9 @@ Date: September 2016 #include #include #include +#include #include #include -// TODO: refined_string_type should be moved to util -#include #include #include "string_refine_preprocess.h" diff --git a/src/solvers/refinement/string_constraint.h b/src/solvers/refinement/string_constraint.h index 61a6f3ebdd6..4b8d1229e09 100644 --- a/src/solvers/refinement/string_constraint.h +++ b/src/solvers/refinement/string_constraint.h @@ -15,7 +15,7 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com #include #include -#include +#include class string_constraintt: public exprt { diff --git a/src/solvers/refinement/string_constraint_generator.h b/src/solvers/refinement/string_constraint_generator.h index 2a56f09fddd..ed898cb9a18 100644 --- a/src/solvers/refinement/string_constraint_generator.h +++ b/src/solvers/refinement/string_constraint_generator.h @@ -14,7 +14,7 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com #define CPROVER_SOLVERS_REFINEMENT_STRING_CONSTRAINT_GENERATOR_H #include -#include +#include #include class string_constraint_generatort diff --git a/src/solvers/refinement/refined_string_type.cpp b/src/util/refined_string_type.cpp similarity index 100% rename from src/solvers/refinement/refined_string_type.cpp rename to src/util/refined_string_type.cpp diff --git a/src/solvers/refinement/refined_string_type.h b/src/util/refined_string_type.h similarity index 93% rename from src/solvers/refinement/refined_string_type.h rename to src/util/refined_string_type.h index 3b36b19e826..477b00139ed 100644 --- a/src/solvers/refinement/refined_string_type.h +++ b/src/util/refined_string_type.h @@ -10,8 +10,8 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com \*******************************************************************/ -#ifndef CPROVER_SOLVERS_REFINEMENT_REFINED_STRING_TYPE_H -#define CPROVER_SOLVERS_REFINEMENT_REFINED_STRING_TYPE_H +#ifndef CPROVER_UTIL_REFINED_STRING_TYPE_H +#define CPROVER_UTIL_REFINED_STRING_TYPE_H #include #include From 2929d7f04a77c3a805c61e09d19c1a9d99423411 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Mon, 27 Feb 2017 11:14:11 +0000 Subject: [PATCH 131/699] Removed distinction between c string type and refined string type --- src/util/refined_string_type.cpp | 9 +++++---- src/util/refined_string_type.h | 4 ---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/util/refined_string_type.cpp b/src/util/refined_string_type.cpp index 3362c71e0db..0625149cf83 100644 --- a/src/util/refined_string_type.cpp +++ b/src/util/refined_string_type.cpp @@ -29,22 +29,23 @@ refined_string_typet::refined_string_typet( array_typet char_array(char_type, infinite_index); components().emplace_back("length", index_type); components().emplace_back("content", char_array); + set_tag(CPROVER_PREFIX"refined_string_type"); } /*******************************************************************\ -Function: refined_string_typet::is_c_string_type +Function: refined_string_typet::is_refined_string_type Inputs: a type - Outputs: Boolean telling whether the type is that of C strings + Outputs: Boolean telling whether the input is a refined string type \*******************************************************************/ -bool refined_string_typet::is_c_string_type(const typet &type) +bool refined_string_typet::is_refined_string_type(const typet &type) { return type.id()==ID_struct && - to_struct_type(type).get_tag()==CPROVER_PREFIX"string"; + to_struct_type(type).get_tag()==CPROVER_PREFIX"refined_string_type"; } diff --git a/src/util/refined_string_type.h b/src/util/refined_string_type.h index 477b00139ed..a0cb7500e7f 100644 --- a/src/util/refined_string_type.h +++ b/src/util/refined_string_type.h @@ -42,10 +42,6 @@ class refined_string_typet: public struct_typet return components()[0].type(); } - // For C the unrefined string type is __CPROVER_string - - static bool is_c_string_type(const typet &type); - static bool is_refined_string_type(const typet &type); constant_exprt index_of_int(int i) const From 5cb0e5e09eac930280c6aa53a0c6be0410700820 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Mon, 27 Feb 2017 11:14:21 +0000 Subject: [PATCH 132/699] Removed mention of c string type Refined string type should be used instead as we are trying to be language independent. --- src/solvers/refinement/string_constraint_generator_main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solvers/refinement/string_constraint_generator_main.cpp b/src/solvers/refinement/string_constraint_generator_main.cpp index 0179a2fcb61..7fe510c2e35 100644 --- a/src/solvers/refinement/string_constraint_generator_main.cpp +++ b/src/solvers/refinement/string_constraint_generator_main.cpp @@ -215,10 +215,10 @@ string_exprt string_constraint_generatort::add_axioms_for_if( const if_exprt &expr) { assert( - refined_string_typet::is_c_string_type(expr.true_case().type())); + refined_string_typet::is_refined_string_type(expr.true_case().type())); string_exprt t=add_axioms_for_string_expr(expr.true_case()); assert( - refined_string_typet::is_c_string_type(expr.false_case().type())); + refined_string_typet::is_refined_string_type(expr.false_case().type())); string_exprt f=add_axioms_for_string_expr(expr.false_case()); const refined_string_typet &ref_type=to_refined_string_type(t.type()); const typet &index_type=ref_type.get_index_type(); From 72ad6ad81ee9e8477390ed64f9836a671fdbc4c7 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Tue, 7 Feb 2017 11:11:47 +0000 Subject: [PATCH 133/699] Making add_string_type more generic The class_name is now passed as argument so that we can reuse this function for StringBuilder and other "String-like" classes. --- .../java_bytecode_convert_class.cpp | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_class.cpp b/src/java_bytecode/java_bytecode_convert_class.cpp index f21b0bb1ce2..7f52c6ef77b 100644 --- a/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/src/java_bytecode/java_bytecode_convert_class.cpp @@ -50,7 +50,16 @@ class java_bytecode_convert_classt:public messaget convert(parse_tree.parsed_class); else if(string_refinement_enabled && parse_tree.parsed_class.name=="java.lang.String") - add_string_type(); + add_string_type("java.lang.String"); + else if(string_refinement_enabled && + parse_tree.parsed_class.name=="java.lang.StringBuilder") + add_string_type("java.lang.StringBuilder"); + else if(string_refinement_enabled && + parse_tree.parsed_class.name=="java.lang.CharSequence") + add_string_type("java.lang.CharSequence"); + else if(string_refinement_enabled && + parse_tree.parsed_class.name=="java.lang.StringBuffer") + add_string_type("java.lang.StringBuffer"); else generate_class_stub(parse_tree.parsed_class.name); } @@ -72,7 +81,7 @@ class java_bytecode_convert_classt:public messaget void generate_class_stub(const irep_idt &class_name); void add_array_types(); - void add_string_type(); + void add_string_type(const irep_idt &class_name); }; /*******************************************************************\ @@ -406,15 +415,17 @@ bool java_bytecode_convert_class( Function: java_bytecode_convert_classt::add_string_type + Inputs: a name for the class such as "java.lang.String" + Purpose: Implements the java.lang.String type in the case that we provide an internal implementation. \*******************************************************************/ -void java_bytecode_convert_classt::add_string_type() +void java_bytecode_convert_classt::add_string_type(const irep_idt &class_name) { class_typet string_type; - string_type.set_tag("java.lang.String"); + string_type.set_tag(class_name); string_type.components().resize(3); string_type.components()[0].set_name("@java.lang.Object"); string_type.components()[0].set_pretty_name("@java.lang.Object"); @@ -432,8 +443,8 @@ void java_bytecode_convert_classt::add_string_type() string_type.add_base(symbol_typet("java::java.lang.Object")); symbolt string_symbol; - string_symbol.name="java::java.lang.String"; - string_symbol.base_name="java.lang.String"; + string_symbol.name="java::"+id2string(class_name); + string_symbol.base_name=id2string(class_name); string_symbol.type=string_type; string_symbol.is_type=true; @@ -445,8 +456,8 @@ void java_bytecode_convert_classt::add_string_type() symbolt string_equals_symbol; string_equals_symbol.name= "java::java.lang.String.equals:(Ljava/lang/Object;)Z"; - string_equals_symbol.base_name="java.lang.String.equals"; - string_equals_symbol.pretty_name="java.lang.String.equals"; + string_equals_symbol.base_name=id2string(class_name)+".equals"; + string_equals_symbol.pretty_name=id2string(class_name)+".equals"; string_equals_symbol.mode=ID_java; code_typet string_equals_type; From c9ff379f11992cafc7a5be00875802f0bd6c7ef5 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Thu, 9 Mar 2017 15:02:08 +0000 Subject: [PATCH 134/699] new identifier for converting char pointer to array --- src/util/irep_ids.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/irep_ids.txt b/src/util/irep_ids.txt index b9d2d253538..1958522eaee 100644 --- a/src/util/irep_ids.txt +++ b/src/util/irep_ids.txt @@ -744,6 +744,7 @@ string_constraint string_not_contains_constraint cprover_char_literal_func cprover_string_literal_func +cprover_string_array_of_char_pointer_func cprover_string_char_at_func cprover_string_char_set_func cprover_string_code_point_at_func From a04dc21fc7d02eafb8fd4d792536707084acf93d Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Fri, 17 Feb 2017 13:18:54 +0000 Subject: [PATCH 135/699] Many corrections in preprocessing of strings Better signatures and string detection Better detection of string-like types and handling of char arrays Changing the way we deal with string initialisation from array Factorized part of type recognition and added StringBuilder and CharSequence to the list of java classes that should be considered as string. Changed the way we deal with StringBuilders: instead of having a map we add an assignment to the instructions. We also detect char arrays and handle them better. We now use substring and copy functions for initialisation from char array since the argument are always transformed into refined strings. For each string returned by a string function we also add into the java_string_to_cprover_string map a string_exprt. Corrected detection of typecast in make_cprover_string_assign Ensuring refined_string arguments of function applications are string_exprt Correct string_refine_preprocesst constructor. Order of initialisation is now the same as the order of declaration. This was picked up by g++ and clang. Added signatures for some StringBuilder functions. Removed map java_to_cprover_string and adapt signature for side effects. The usage of a map is not correct since strings can be modified by side effects. Signature is necessary for StringBuilders to be assigned in the right way with methods with side effects. Assign all string_exprt to refined string symbols in preprocessing. This makes it then easier to debug and to find witnesses for counter examples in the solver. Make signatures take priority over actual type and add signature for intern. Linting corrections Adding malloc for char arrays for String.toCharArray Fixing preprocessing of string function with side effect This fixes problems we were getting with some StringBuilder functions. The return value should contain a pointer to the original StringBuilder and the fields of the StringBuilder should be filled with the result of the function call. Corrected mistake in preprocessing of string functions with side effects char array assignements returns a string_exprt This is to be uniform with other preprocessing functions also returning string_exprt Preprocessing for StringBuilder.append on char array Corrected update of signature and commented out some unused code Corrected the initialization from char array We cannot use the substring function because the meaning of the third argument is different between `String.([CII)` and `String.substring(SII)` Using new id for conversion between char pointer and array Cleaning of preprocessing for strings Removed useless functions and merged some maps Make a copy of the function call to be modified Removed redeclaration of location --- .../string_refine_preprocess.cpp | 797 +++++++++--------- src/goto-programs/string_refine_preprocess.h | 71 +- 2 files changed, 416 insertions(+), 452 deletions(-) diff --git a/src/goto-programs/string_refine_preprocess.cpp b/src/goto-programs/string_refine_preprocess.cpp index ec02988d577..8403d4bf044 100644 --- a/src/goto-programs/string_refine_preprocess.cpp +++ b/src/goto-programs/string_refine_preprocess.cpp @@ -23,6 +23,32 @@ Date: September 2016 /*******************************************************************\ +Function: string_refine_preprocesst::check_java_type + + Inputs: a type and a string + + Outputs: Boolean telling whether the type is a struct with the given + tag or a symbolic type with the tag prefixed by "java::" + +\*******************************************************************/ + +bool string_refine_preprocesst::check_java_type( + const typet &type, const std::string &tag) +{ + if(type.id()==ID_symbol) + { + irep_idt tag_id=to_symbol_type(type).get_identifier(); + return tag_id=="java::"+tag; + } + else if(type.id()==ID_struct) + { + irep_idt tag_id=to_struct_type(type).get_tag(); + return tag_id==tag; + } + return false; +} +/*******************************************************************\ + Function: string_refine_preprocesst::is_java_string_pointer_type Inputs: a type @@ -54,17 +80,7 @@ Function: string_refine_preprocesst::is_java_string_type bool string_refine_preprocesst::is_java_string_type(const typet &type) { - if(type.id()==ID_symbol) - { - const irep_idt &tag=to_symbol_type(type).get_identifier(); - return tag=="java::java.lang.String"; - } - else if(type.id()==ID_struct) - { - const irep_idt &tag=to_struct_type(type).get_tag(); - return tag=="java.lang.String"; - } - return false; + return check_java_type(type, "java.lang.String"); } /*******************************************************************\ @@ -79,17 +95,7 @@ Function: string_refine_preprocesst::is_java_string_builder_type bool string_refine_preprocesst::is_java_string_builder_type(const typet &type) { - if(type.id()==ID_pointer) - { - const pointer_typet &pt=to_pointer_type(type); - const typet &subtype=pt.subtype(); - if(subtype.id()==ID_struct) - { - const irep_idt &tag=to_struct_type(subtype).get_tag(); - return tag=="java.lang.StringBuilder"; - } - } - return false; + return check_java_type(type, "java.lang.StringBuilder"); } /*******************************************************************\ @@ -114,6 +120,7 @@ bool string_refine_preprocesst::is_java_string_builder_pointer_type( } return false; } + /*******************************************************************\ Function: string_refine_preprocesst::is_java_char_sequence_type @@ -125,16 +132,67 @@ Function: string_refine_preprocesst::is_java_char_sequence_type \*******************************************************************/ bool string_refine_preprocesst::is_java_char_sequence_type(const typet &type) +{ + return check_java_type(type, "java.lang.CharSequence"); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::is_java_char_sequence_pointer_type + + Inputs: a type + + Outputs: Boolean telling whether the type is that of a pointer + to a java char sequence + +\*******************************************************************/ + +bool string_refine_preprocesst::is_java_char_sequence_pointer_type( + const typet &type) { if(type.id()==ID_pointer) { const pointer_typet &pt=to_pointer_type(type); const typet &subtype=pt.subtype(); - if(subtype.id()==ID_struct) - { - const irep_idt &tag=to_struct_type(subtype).get_tag(); - return tag=="java.lang.CharSequence"; - } + return is_java_char_sequence_type(subtype); + } + return false; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::is_java_char_array_type + + Inputs: a type + + Outputs: Boolean telling whether the type is that of java char array + +\*******************************************************************/ + +bool string_refine_preprocesst::is_java_char_array_type(const typet &type) +{ + return check_java_type(type, "array[char]"); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::is_java_char_array_pointer_type + + Inputs: a type + + Outputs: Boolean telling whether the type is that of a pointer + to a java char array + +\*******************************************************************/ + +bool string_refine_preprocesst::is_java_char_array_pointer_type( + const typet &type) +{ + if(type.id()==ID_pointer) + { + const pointer_typet &pt=to_pointer_type(type); + const typet &subtype=pt.subtype(); + return is_java_char_array_type(subtype); } return false; } @@ -217,6 +275,32 @@ void string_refine_preprocesst::declare_function( /*******************************************************************\ +Function: string_refine_preprocesst::get_data_and_length_type_of_char_array + + Inputs: an expression, a reference to a data type and a reference to a + length type + + Purpose: assuming the expression is a char array, figure out what + the types for length and data are and put them into the references + given as argument + +\*******************************************************************/ + +void string_refine_preprocesst::get_data_and_length_type_of_char_array( + const exprt &expr, typet &data_type, typet &length_type) +{ + typet object_type=ns.follow(expr.type()); + assert(object_type.id()==ID_struct); + const struct_typet &struct_type=to_struct_type(object_type); + for(auto component : struct_type.components()) + if(component.get_name()=="length") + length_type=component.type(); + else if(component.get_name()=="data") + data_type=component.type(); +} + +/*******************************************************************\ + Function: string_refine_preprocesst::get_data_and_length_type_of_string Inputs: an expression, a reference to a data type and a reference to a @@ -232,7 +316,8 @@ void string_refine_preprocesst::get_data_and_length_type_of_string( const exprt &expr, typet &data_type, typet &length_type) { assert(is_java_string_type(expr.type()) || - is_java_string_builder_type(expr.type())); + is_java_string_builder_type(expr.type()) || + is_java_char_sequence_type(expr.type())); typet object_type=ns.follow(expr.type()); const struct_typet &struct_type=to_struct_type(object_type); for(const auto &component : struct_type.components()) @@ -263,44 +348,43 @@ exprt string_refine_preprocesst::make_cprover_string_assign( const exprt &rhs, const source_locationt &location) { - if(is_java_string_pointer_type(rhs.type())) + if(implements_java_char_sequence(rhs.type())) { - auto pair=java_to_cprover_strings.insert( - std::pair(rhs, nil_exprt())); - - if(pair.second) - { - // We do the following assignments: - // cprover_string_array = *(rhs->data) - // cprover_string = { rhs->length; cprover_string_array } - - dereference_exprt deref(rhs, rhs.type().subtype()); - - typet data_type, length_type; - get_data_and_length_type_of_string(deref, data_type, length_type); - member_exprt length(deref, "length", length_type); - symbol_exprt array_lhs=fresh_array(data_type.subtype(), location); - - // string expression for the rhs of the second assignment - string_exprt new_rhs( - length, array_lhs, refined_string_typet(length_type, data_type)); - - member_exprt data(deref, "data", data_type); - dereference_exprt deref_data(data, data_type.subtype()); - symbol_exprt lhs=fresh_string(new_rhs.type(), location); - - std::list assignments; - assignments.emplace_back(array_lhs, deref_data); - assignments.emplace_back(lhs, new_rhs); - insert_assignments( - goto_program, target, target->function, location, assignments); - target=goto_program.insert_after(target); - pair.first->second=lhs; - } - return pair.first->second; + // We do the following assignments: + // 1 length= *(rhs->length) + // 2 cprover_string_array = *(rhs->data) + // 3 cprover_string = { length; cprover_string_array } + + dereference_exprt deref(rhs, rhs.type().subtype()); + typet data_type, length_type; + get_data_and_length_type_of_string(deref, data_type, length_type); + std::list assignments; + + // 1) cprover_string_length= *(rhs->length) + member_exprt length(deref, "length", length_type); + + // 2) cprover_string_array = *(rhs->data) + symbol_exprt array_lhs=fresh_array(data_type.subtype(), location); + member_exprt data(deref, "data", data_type); + dereference_exprt deref_data(data, data_type.subtype()); + assignments.emplace_back(array_lhs, deref_data); + + // 3) cprover_string = { cprover_string_length; cprover_string_array } + // This assignment is useful for finding witnessing strings for counter + // examples + refined_string_typet ref_type(length_type, java_char_type()); + string_exprt new_rhs(length, array_lhs, ref_type); + + symbol_exprt lhs=fresh_string(new_rhs.type(), location); + assignments.emplace_back(lhs, new_rhs); + + insert_assignments( + goto_program, target, target->function, location, assignments); + target=goto_program.insert_after(target); + return new_rhs; } else if(rhs.id()==ID_typecast && - is_java_string_pointer_type(rhs.op0().type())) + implements_java_char_sequence(rhs.op0().type())) { exprt new_rhs=make_cprover_string_assign( goto_program, target, rhs.op0(), location); @@ -312,6 +396,75 @@ exprt string_refine_preprocesst::make_cprover_string_assign( /*******************************************************************\ +Function: string_refine_preprocesst::make_cprover_char_array_assign + + Inputs: a goto_program, a position in this program, an expression of + type char array pointer and a location + + Outputs: a string expression + + Purpose: Introduce a temporary variable for cprover strings; + returns the cprover_string corresponding to rhs + +\*******************************************************************/ + +string_exprt string_refine_preprocesst::make_cprover_char_array_assign( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &rhs, + const source_locationt &location) +{ + assert(is_java_char_array_pointer_type(rhs.type())); + + // We do the following assignments: + // deref=*(rhs->data) + // array= typecast(&deref); + // string={ rhs->length; array } + + dereference_exprt deref(rhs, rhs.type().subtype()); + typet length_type, data_type; + get_data_and_length_type_of_char_array(deref, data_type, length_type); + assert(data_type.id()==ID_pointer); + typet char_type=to_pointer_type(data_type).subtype(); + + refined_string_typet ref_type(length_type, java_char_type()); + typet content_type=ref_type.get_content_type(); + std::list assignments; + + // deref=*(rhs->data) + member_exprt array_rhs(deref, "data", data_type); + dereference_exprt deref_array(array_rhs, data_type.subtype()); + symbolt sym_lhs_deref=get_fresh_aux_symbol( + data_type.subtype(), + "char_array_assign$deref", + "char_array_assign$deref", + location, + ID_java, + symbol_table); + symbol_exprt lhs_deref=sym_lhs_deref.symbol_expr(); + assignments.emplace_back(lhs_deref, deref_array); + + // array=convert_pointer_to_char_array(*rhs->data) + declare_function(ID_cprover_string_array_of_char_pointer_func, content_type); + function_application_exprt fun_app(symbol_exprt( + ID_cprover_string_array_of_char_pointer_func), content_type); + fun_app.arguments().push_back(deref_array); + symbol_exprt array=fresh_array(content_type, location); + assignments.emplace_back(array, fun_app); + + // string={ rhs->length; string_array } + string_exprt new_rhs(get_length(deref, length_type), array, ref_type); + symbol_exprt lhs=fresh_string(ref_type, location); + assignments.emplace_back(lhs, new_rhs); + + insert_assignments( + goto_program, target, target->function, location, assignments); + target=goto_program.insert_after(target); + return new_rhs; +} + +/*******************************************************************\ + Function: string_refine_preprocesst::make_normal_assign Inputs: a goto_program, a position in this program, an expression lhs, @@ -336,27 +489,19 @@ void string_refine_preprocesst::make_normal_assign( const source_locationt &location, const std::string &signature) { - if(function_name==ID_cprover_string_copy_func) - { - assert(!arguments.empty()); - make_string_copy(goto_program, target, lhs, arguments[0], location); - } - else - { - function_application_exprt rhs( - symbol_exprt(function_name), function_type.return_type()); - rhs.add_source_location()=location; - declare_function(function_name, function_type); + function_application_exprt rhs( + symbol_exprt(function_name), function_type.return_type()); + rhs.add_source_location()=location; + declare_function(function_name, function_type); - exprt::operandst processed_arguments=process_arguments( - goto_program, target, arguments, location, signature); - rhs.arguments()=processed_arguments; + exprt::operandst processed_arguments=process_arguments( + goto_program, target, arguments, location, signature); + rhs.arguments()=processed_arguments; - code_assignt assignment(lhs, rhs); - assignment.add_source_location()=location; - target->make_assignment(); - target->code=assignment; - } + code_assignt assignment(lhs, rhs); + assignment.add_source_location()=location; + target->make_assignment(); + target->code=assignment; } /*******************************************************************\ @@ -420,7 +565,7 @@ void string_refine_preprocesst::make_string_assign( const source_locationt &location, const std::string &signature) { - assert(is_java_string_pointer_type(function_type.return_type())); + assert(implements_java_char_sequence(function_type.return_type())); dereference_exprt deref(lhs, lhs.type().subtype()); typet object_type=ns.follow(deref.type()); exprt object_size=size_of_expr(object_type, ns); @@ -454,98 +599,22 @@ void string_refine_preprocesst::make_string_assign( malloc_expr.type()=pointer_typet(object_type); malloc_expr.add_source_location()=location; + refined_string_typet ref_type(length_type, data_type.subtype().subtype()); + string_exprt str(tmp_length, tmp_array, ref_type); + symbol_exprt cprover_string_sym=fresh_string(ref_type, location); + std::list assigns; assigns.emplace_back(lhs, malloc_expr); assigns.emplace_back(tmp_length, rhs_length); assigns.emplace_back(lhs_length, tmp_length); assigns.emplace_back(tmp_array, rhs_data); + assigns.emplace_back(cprover_string_sym, str); assigns.emplace_back(lhs_data, address_of_exprt(tmp_array)); insert_assignments(goto_program, target, target->function, location, assigns); } /*******************************************************************\ -Function: string_refine_preprocesst::make_assign - - Inputs: a goto_program, a position in this program, an expression lhs, - a function type, a function name, a vector of arguments, a location - and a signature - - Purpose: assign the result of the function application to lhs, - in case the function type is string, it does a special assignment - using `make_string_assign` - -\*******************************************************************/ - -void string_refine_preprocesst::make_assign( - goto_programt &goto_program, - goto_programt::targett &target, - const exprt &lhs, - const code_typet &function_type, - const irep_idt &function_name, - const exprt::operandst &arg, - const source_locationt &loc, - const std::string &sig) -{ - if(is_java_string_pointer_type(function_type.return_type())) - make_string_assign( - goto_program, target, lhs, function_type, function_name, arg, loc, sig); - else - make_normal_assign( - goto_program, target, lhs, function_type, function_name, arg, loc, sig); -} - -/*******************************************************************\ - -Function: string_refine_preprocesst::make_string_copy - - Inputs: a goto_program, a position in this program, a lhs expression, - an argument expression and a location - - Outputs: an expression - - Purpose: replace the current instruction by: - > lhs->length=argument->length - > tmp_data=*(argument->data) - > lhs->data=&tmp_data - -\*******************************************************************/ - -void string_refine_preprocesst::make_string_copy( - goto_programt &goto_program, - goto_programt::targett &target, - const exprt &lhs, - const exprt &argument, - const source_locationt &location) -{ - // TODO : treat CharSequence and StringBuffer - assert(is_java_string_pointer_type(lhs.type()) || - is_java_string_builder_pointer_type(lhs.type())); - exprt deref=dereference_exprt(lhs, lhs.type().subtype()); - - typet length_type, data_type; - get_data_and_length_type_of_string(deref, data_type, length_type); - - dereference_exprt deref_arg(argument, argument.type().subtype()); - std::list assignments; - - exprt lhs_length=get_length(deref, length_type); - exprt rhs_length=get_length(deref_arg, length_type); - assignments.emplace_back(lhs_length, rhs_length); - - symbol_exprt tmp_data=fresh_array(data_type.subtype(), location); - exprt rhs_data=get_data(deref_arg, data_type); - exprt lhs_data=get_data(deref, data_type); - assignments.emplace_back( - tmp_data, dereference_exprt(rhs_data, data_type.subtype())); - assignments.emplace_back(lhs_data, address_of_exprt(tmp_data)); - - insert_assignments( - goto_program, target, target->function, location, assignments); -} - -/*******************************************************************\ - Function: string_refine_preprocesst::make_string_function Inputs: a position in a goto program, a function name, an expression lhs, @@ -566,7 +635,36 @@ void string_refine_preprocesst::make_string_function( const source_locationt &location, const std::string &signature) { - if(is_java_string_pointer_type(function_type.return_type())) + if(signature.length()>0) + { + if(signature.back()=='S') + { + code_typet ft=function_type; + ft.return_type()=jls_ptr; + typecast_exprt lhs2(lhs, jls_ptr); + + make_string_assign( + goto_program, + target, + lhs2, + ft, + function_name, + arguments, + location, + signature); + } + else + make_normal_assign( + goto_program, + target, + lhs, + function_type, + function_name, + arguments, + location, + signature); + } + else if(implements_java_char_sequence(function_type.return_type())) make_string_assign( goto_program, target, @@ -597,9 +695,11 @@ Function: string_refine_preprocesst::make_string_function Purpose: at the current position replace `lhs=s.some_function(x,...)` by `lhs=function_name(s,x,...)`; option `assign_first_arg` uses `s` instead of `lhs` in the resulting - expression; + expression, Warning : it assumes that `s` is string-like option `skip_first_arg`, removes `s` from the arguments, ie `x` is - the first one + the first one; + arguments that are string (TODO: and char array) are replaced + by string_exprt \*******************************************************************/ @@ -635,11 +735,17 @@ void string_refine_preprocesst::make_string_function( new_type.parameters().push_back(function_type.parameters()[i]); } + std::string new_sig=signature; exprt lhs; if(assign_first_arg) { assert(!function_call.arguments().empty()); lhs=function_call.arguments()[0]; + std::size_t size=function_call.arguments().size(); + if(signature.length()<=size) + new_sig.resize(size+1, '_'); + + new_sig.replace(size, 1, "S"); } else lhs=function_call.lhs(); @@ -650,7 +756,7 @@ void string_refine_preprocesst::make_string_function( new_type.return_type()=lhs.type(); make_string_function( - goto_program, target, lhs, new_type, function_name, args, loc, signature); + goto_program, target, lhs, new_type, function_name, args, loc, new_sig); } /*******************************************************************\ @@ -680,9 +786,11 @@ Function: string_refine_preprocesst::make_string_function_side_effect Inputs: a position in a goto program and a function name - Purpose: at the current position, replace `r=s.some_function(x,...)` - by `s=function_name(s,x,...)` and add a correspondance from r - to s in the `string_builders` map + Purpose: at the current position, replace `r=s.some_function(x,...)` by + > tmp=function_name(x,...) + > s->data=tmp.data + > s->length=tmp.length + > r=s \*******************************************************************/ @@ -692,11 +800,48 @@ void string_refine_preprocesst::make_string_function_side_effect( const irep_idt &function_name, const std::string &signature) { - const code_function_callt function_call=to_code_function_call(target->code); - assert(!function_call.arguments().empty()); - string_builders[function_call.lhs()]=function_call.arguments()[0]; - make_string_function( - goto_program, target, function_name, signature, true, false); + code_function_callt function_call=to_code_function_call(target->code); + source_locationt loc=function_call.source_location(); + std::list assignments; + exprt lhs=function_call.lhs(); + exprt s=function_call.arguments()[0]; + code_typet function_type=to_code_type(function_call.type()); + + function_type.return_type()=s.type(); + + if(lhs.is_not_nil()) + { + symbol_exprt tmp_string=fresh_string(lhs.type(), loc); + + make_string_assign( + goto_program, + target, + tmp_string, + function_type, + function_name, + function_call.arguments(), + loc, + signature); + dereference_exprt deref_lhs(s, s.type().subtype()); + typet data_type, length_type; + get_data_and_length_type_of_string(deref_lhs, data_type, length_type); + member_exprt lhs_data(deref_lhs, "data", data_type); + member_exprt lhs_length(deref_lhs, "length", length_type); + dereference_exprt deref_rhs(tmp_string, s.type().subtype()); + member_exprt rhs_data(deref_rhs, "data", data_type); + member_exprt rhs_length(deref_rhs, "length", length_type); + assignments.emplace_back(lhs_length, rhs_length); + assignments.emplace_back(lhs_data, rhs_data); + assignments.emplace_back(lhs, s); + target=goto_program.insert_after(target); + insert_assignments( + goto_program, target, target->function, loc, assignments); + } + else + { + make_string_function( + goto_program, target, function_name, signature, true, false); + } } /*******************************************************************\ @@ -735,6 +880,7 @@ Function: string_refine_preprocesst::make_to_char_array_function Inputs: a goto program and a position in that goto program Purpose: at the given position replace `return_tmp0=s.toCharArray()` with: + > return_tmp0 = malloc(array[char]); > return_tmp0->data=&((s->data)[0]) > return_tmp0->length=s->length @@ -744,16 +890,36 @@ void string_refine_preprocesst::make_to_char_array_function( goto_programt &goto_program, goto_programt::targett &target) { const code_function_callt &function_call=to_code_function_call(target->code); + source_locationt location=function_call.source_location(); - assert(!function_call.arguments().empty()); + assert(function_call.arguments().size()>=1); const exprt &string_argument=function_call.arguments()[0]; assert(is_java_string_pointer_type(string_argument.type())); + typet deref_type=function_call.lhs().type().subtype(); + const exprt &lhs=function_call.lhs(); + dereference_exprt deref_lhs(lhs, deref_type); + dereference_exprt deref(string_argument, string_argument.type().subtype()); typet length_type, data_type; get_data_and_length_type_of_string(deref, data_type, length_type); std::list assignments; + // lhs=malloc(array[char]) + typet object_type=ns.follow(deref_type); + exprt object_size=size_of_expr(object_type, ns); + + if(object_size.is_nil()) + debug() << "string_refine_preprocesst::make_to_char_array_function " + << "got nil object_size" << eom; + + side_effect_exprt malloc_expr(ID_malloc); + malloc_expr.copy_to_operands(object_size); + malloc_expr.type()=pointer_typet(object_type); + malloc_expr.add_source_location()=location; + assignments.emplace_back(lhs, malloc_expr); + + // &((s->data)[0]) exprt rhs_data=get_data(deref, data_type); dereference_exprt rhs_array(rhs_data, data_type.subtype()); @@ -762,8 +928,6 @@ void string_refine_preprocesst::make_to_char_array_function( address_of_exprt rhs_pointer(first_element); // return_tmp0->data=&((s->data)[0]) - typet deref_type=function_call.lhs().type().subtype(); - dereference_exprt deref_lhs(function_call.lhs(), deref_type); exprt lhs_data=get_data(deref_lhs, data_type); assignments.emplace_back(lhs_data, rhs_pointer); @@ -771,178 +935,8 @@ void string_refine_preprocesst::make_to_char_array_function( exprt rhs_length=get_length(deref, length_type); exprt lhs_length=get_length(deref_lhs, length_type); assignments.emplace_back(lhs_length, rhs_length); - source_locationt location=target->source_location; - insert_assignments( - goto_program, target, target->function, location, assignments); -} - -/*******************************************************************\ - -Function: string_refine_preprocesst::make_cprover_char_array_assign - - Inputs: a goto_program, a position in this program, an expression and a - location - - Outputs: a char array expression (not a pointer) - - Purpose: Introduce a temporary variable for cprover strings; - returns the cprover_string corresponding to rhs - -\*******************************************************************/ - -exprt string_refine_preprocesst::make_cprover_char_array_assign( - goto_programt &goto_program, - goto_programt::targett &target, - const exprt &rhs, - const source_locationt &location) -{ - // TODO : add an assertion on the type of rhs - - // We do the following assignments: - // cprover_string_array = rhs.data - // cprover_string = { rhs.length; cprover_string_array } - - // string expression for the rhs of the second assignment - string_exprt new_rhs(java_char_type()); - - typet data_type=new_rhs.content().type(); - typet length_type=java_int_type(); - - symbol_exprt array_lhs=fresh_array(data_type, location); - exprt array_rhs=get_data(rhs, new_rhs.content().type()); - symbol_exprt lhs=fresh_string(new_rhs.type(), location); - new_rhs.length()=get_length(rhs, length_type); - new_rhs.content()=array_lhs; - - std::list assignments; - assignments.emplace_back(array_lhs, array_rhs); - assignments.emplace_back(lhs, new_rhs); insert_assignments( goto_program, target, target->function, location, assignments); - target=goto_program.insert_after(target); - return lhs; -} - -/*******************************************************************\ - -Function: string_refine_preprocesst::make_char_array_function - - Inputs: a position in a goto program, a function name, two Boolean options, - and the index of the char array argument in the function - - Purpose: at the given position replace - `lhs=s.some_function(...,char_array,...)` by - > cprover_string = { char_array->length, *char_array } - > tmp_string=function_name(s, cprover_string, ...) - option `assign_first_arg` uses `s` instead of `lhs` in the second - assignment; - option `skip_first_arg`, removes `s` from the arguments, ie `x` is - the first one; - argument index gives the index of the argument containing char_array - -\*******************************************************************/ - -void string_refine_preprocesst::make_char_array_function( - goto_programt &goto_program, - goto_programt::targett &target, - const irep_idt &function_name, - const std::string &signature, - std::size_t index, - bool assign_first_arg, - bool skip_first_arg) -{ - code_function_callt &function_call=to_code_function_call(target->code); - code_typet function_type=to_code_type(function_call.function().type()); - code_typet new_function_type; - const source_locationt &location=function_call.source_location(); - assert(!function_call.arguments().size()>index); - const std::vector &args=function_call.arguments(); - std::vector new_args; - - exprt lhs; - if(assign_first_arg) - { - assert(!function_call.arguments().empty()); - lhs=function_call.arguments()[0]; - else - lhs=function_call.lhs(); - - if(lhs.id()==ID_typecast) - lhs=to_typecast_expr(lhs).op(); - - exprt char_array=dereference_exprt( - function_call.arguments()[index], - function_call.arguments()[index].type().subtype()); - exprt string=make_cprover_char_array_assign( - goto_program, target, char_array, location); - - std::size_t start_index=skip_first_arg?1:0; - for(std::size_t i=start_index; icode); - assert(!function_call.arguments().empty()); - string_builders[function_call.lhs()]=function_call.arguments()[0]; } /*******************************************************************\ @@ -974,22 +968,20 @@ exprt::operandst string_refine_preprocesst::process_arguments( for(std::size_t i=0; isecond); - else + if(iis_function_call()) { code_function_callt &function_call=to_code_function_call(target->code); - for(auto &arg : function_call.arguments()) - { - auto sb_it=string_builders.find(arg); - if(sb_it!=string_builders.end()) - arg=sb_it->second; - } if(function_call.function().id()==ID_symbol) { @@ -1070,21 +1056,6 @@ void string_refine_preprocesst::replace_string_calls( make_string_function_call( goto_program, target, it->second, signature); - it=string_of_char_array_functions.find(function_id); - if(it!=string_of_char_array_functions.end()) - make_char_array_function( - goto_program, target, it->second, signature, 0); - - it=string_of_char_array_function_calls.find(function_id); - if(it!=string_of_char_array_function_calls.end()) - make_char_array_function_call( - goto_program, target, it->second, signature); - - it=side_effect_char_array_functions.find(function_id); - if(it!=side_effect_char_array_functions.end()) - make_char_array_side_effect( - goto_program, target, it->second, signature); - if(function_id==irep_idt("java::java.lang.String.toCharArray:()[C")) make_to_char_array_function(goto_program, target); } @@ -1299,12 +1270,18 @@ void string_refine_preprocesst::initialize_string_function_table() ID_cprover_string_set_length_func; - side_effect_char_array_functions + + side_effect_functions + ["java::java.lang.StringBuilder.append:([C)" + "Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_func; + side_effect_functions ["java::java.lang.StringBuilder.insert:(I[CII)Ljava/lang/StringBuilder;"]= - ID_cprover_string_insert_char_array_func; - side_effect_char_array_functions + ID_cprover_string_insert_func; + side_effect_functions ["java::java.lang.StringBuilder.insert:(I[C)Ljava/lang/StringBuilder;"]= - ID_cprover_string_insert_char_array_func; + ID_cprover_string_insert_func; + // TODO clean irep ids from insert_char_array etc... string_function_calls ["java::java.lang.String.:(Ljava/lang/String;)V"]= @@ -1320,23 +1297,23 @@ void string_refine_preprocesst::initialize_string_function_table() string_function_calls["java::java.lang.StringBuilder.:()V"]= ID_cprover_string_empty_string_func; - string_of_char_array_function_calls["java::java.lang.String.:([C)V"]= - ID_cprover_string_of_char_array_func; - string_of_char_array_function_calls["java::java.lang.String.:([CII)V"]= - ID_cprover_string_of_char_array_func; + string_function_calls["java::java.lang.String.:([C)V"]= + ID_cprover_string_copy_func; + string_function_calls["java::java.lang.String.:([CII)V"]= + ID_cprover_string_copy_func; - string_of_char_array_functions + string_functions ["java::java.lang.String.valueOf:([CII)Ljava/lang/String;"]= - ID_cprover_string_of_char_array_func; - string_of_char_array_functions + ID_cprover_string_copy_func; + string_functions ["java::java.lang.String.valueOf:([C)Ljava/lang/String;"]= - ID_cprover_string_of_char_array_func; - string_of_char_array_functions + ID_cprover_string_copy_func; + string_functions ["java::java.lang.String.copyValueOf:([CII)Ljava/lang/String;"]= - ID_cprover_string_of_char_array_func; - string_of_char_array_functions + ID_cprover_string_copy_func; + string_functions ["java::java.lang.String.copyValueOf:([C)Ljava/lang/String;"]= - ID_cprover_string_of_char_array_func; + ID_cprover_string_copy_func; c_string_functions["__CPROVER_uninterpreted_string_literal_func"]= ID_cprover_string_literal_func; @@ -1370,9 +1347,23 @@ void string_refine_preprocesst::initialize_string_function_table() ID_cprover_string_of_int_func; signatures["java::java.lang.String.equals:(Ljava/lang/Object;)Z"]="SSZ"; - signatures - ["java::java.lang.String.contains:(Ljava/lang/CharSequence;)Z"]= - "SSZ"; + signatures["java::java.lang.String.contains:(Ljava/lang/CharSequence;)Z"]= + "SSZ"; + signatures["java::java.lang.StringBuilder.insert:(IZ)" + "Ljava/lang/StringBuilder;"]="SIZS"; + signatures["java::java.lang.StringBuilder.insert:(IJ)" + "Ljava/lang/StringBuilder;"]="SIJS"; + signatures["java::java.lang.StringBuilder.insert:(II)" + "Ljava/lang/StringBuilder;"]="SIIS"; + signatures["java::java.lang.StringBuilder.insert:(IC)" + "Ljava/lang/StringBuilder;"]="SICS"; + signatures["java::java.lang.StringBuilder.insert:(ILjava/lang/String;)" + "Ljava/lang/StringBuilder;"]="SISS"; + signatures["java::java.lang.StringBuilder.insert:(ILjava/lang/String;)" + "Ljava/lang/StringBuilder;"]="SISS"; + signatures["java::java.lang.StringBuilder.insert:(I[C)" + "Ljava/lang/StringBuilder;"]="SI[S"; + signatures["java::java.lang.String.intern:()Ljava/lang/String;"]="SV"; } /*******************************************************************\ diff --git a/src/goto-programs/string_refine_preprocess.h b/src/goto-programs/string_refine_preprocess.h index 613d0161926..5ae398b757a 100644 --- a/src/goto-programs/string_refine_preprocess.h +++ b/src/goto-programs/string_refine_preprocess.h @@ -14,6 +14,7 @@ Date: September 2016 #include #include +#include class string_refine_preprocesst:public messaget { @@ -29,28 +30,21 @@ class string_refine_preprocesst:public messaget typedef std::unordered_map id_mapt; typedef std::unordered_map expr_mapt; - // String builders maps the different names of a same StringBuilder object - // to a unique expression. - expr_mapt string_builders; - // Map name of Java string functions to there equivalent in the solver id_mapt side_effect_functions; id_mapt string_functions; id_mapt c_string_functions; id_mapt string_function_calls; - id_mapt string_of_char_array_functions; - id_mapt string_of_char_array_function_calls; - id_mapt side_effect_char_array_functions; std::unordered_map signatures; - expr_mapt hidden_strings; - expr_mapt java_to_cprover_strings; // unique id for each newly created symbols int next_symbol_id; void initialize_string_function_table(); + static bool check_java_type(const typet &type, const std::string &tag); + static bool is_java_string_pointer_type(const typet &type); static bool is_java_string_type(const typet &type); @@ -61,6 +55,20 @@ class string_refine_preprocesst:public messaget static bool is_java_char_sequence_type(const typet &type); + static bool is_java_char_sequence_pointer_type(const typet &type); + + static bool is_java_char_array_type(const typet &type); + + static bool is_java_char_array_pointer_type(const typet &type); + + static bool implements_java_char_sequence(const typet &type) + { + return + is_java_char_sequence_pointer_type(type) || + is_java_string_builder_pointer_type(type) || + is_java_string_pointer_type(type); + } + symbol_exprt fresh_array( const typet &type, const source_locationt &location); symbol_exprt fresh_string( @@ -110,6 +118,9 @@ class string_refine_preprocesst:public messaget void get_data_and_length_type_of_string( const exprt &expr, typet &data_type, typet &length_type); + void get_data_and_length_type_of_char_array( + const exprt &expr, typet &data_type, typet &length_type); + function_application_exprt build_function_application( const irep_idt &function_name, const typet &type, @@ -136,27 +147,16 @@ class string_refine_preprocesst:public messaget const source_locationt &location, const std::string &signature); - void make_assign( - goto_programt &goto_program, - goto_programt::targett &target, - const exprt &lhs, - const code_typet &function_type, - const irep_idt &function_name, - const exprt::operandst &arg, - const source_locationt &loc, - const std::string &sig); - exprt make_cprover_string_assign( goto_programt &goto_program, goto_programt::targett &target, const exprt &rhs, const source_locationt &location); - void make_string_copy( + string_exprt make_cprover_char_array_assign( goto_programt &goto_program, goto_programt::targett &target, - const exprt &lhs, - const exprt &argument, + const exprt &rhs, const source_locationt &location); void make_string_function( @@ -192,33 +192,6 @@ class string_refine_preprocesst:public messaget void make_to_char_array_function( goto_programt &goto_program, goto_programt::targett &); - exprt make_cprover_char_array_assign( - goto_programt &goto_program, - goto_programt::targett &target, - const exprt &rhs, - const source_locationt &location); - - void make_char_array_function( - goto_programt &goto_program, - goto_programt::targett &target, - const irep_idt &function_name, - const std::string &signature, - std::size_t index, - bool assign_first_arg=false, - bool skip_first_arg=false); - - void make_char_array_function_call( - goto_programt &goto_program, - goto_programt::targett &target, - const irep_idt &function_name, - const std::string &signature); - - void make_char_array_side_effect( - goto_programt &goto_program, - goto_programt::targett &target, - const irep_idt &function_name, - const std::string &signature); - void replace_string_calls(goto_functionst::function_mapt::iterator f_it); }; From bdbeaf586aa45a429b0fa390169514e5d2a3c7ad Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Tue, 28 Feb 2017 13:50:25 +0000 Subject: [PATCH 136/699] Many corrections in string refinement Overhaul of string solver contributions The code adding lemmas to the solver for each equality has been completely remastered. It has been simplified and should now cover all foreseable cases. Add overflow constraints on sums for string solver When creating sum expressions during string refinement, e.g. when adding string lengths, we shall add axioms to prevent the solver from finding values that actually come from an integer overflow. Therefore, we introduce a new method plus_exprt_with_overflow_check() that wraps around plus_exprt and generates the relevant axioms. Cache function applications Cache converted function applications to avoid re-generating the axioms if it has already been done for a given function application. This seems to happen for function applications that are in an assertion, and thus are treated separately by convert_bitvector. Remove string_refinement::convert_symbol: the behaviour of this function was to convert java strings to strings of symbols. In hindsight, this was not a good idea, as we still refer to the actual java string fields in some cases, e.g. to read its length. Replace add_axioms_for_string_expr In all add_axioms_... methods, we replace all calls to add_axioms_for_string_expr by the newly created function get_string_expr, which simply returns a string_exprt when we give it an refined expr (such as a string_exprt or a symbol). Update doc in add_axioms_for_index_string Simplify constraint for is_prefix: apply distribution law and update (and refactor) documentation. Remove set_string_symbol_equal_to_expr() Removed mentions of java string type in the string solver Removing mentions of is_c_string_type To use the string solver in C, we should use a struct type with tag __CPROVER_refined_string_type Keep non-string axioms in a list Instead of giving axioms to super::boolbv_set_equality_to_true, which may contain un-substituted symbols, we keep them in a list and substitute them in dec_solve() before giving them to the function. Cleaning the add_axioms_for_string_expr method and renamed it to add_axioms_for_refined_string to signify that it should only be called on expression of type refined string. An assertion was added at the beginning to ensure that. Better get_array and string_of_array functions. Cleaned the implementation of get_array and factorized part of it. Made string_of_array directly take a array_exprt, which can be obtained from get_array. Improved string_of_array for non printable characters Resolve symbol to char arrays in non-string axioms. We introduce a mapping that expresses the maximal traversal of symbols of char array type. We use that map to, either obtain a char array from a symbol, either get a unique symbol the aliases equivalence class. This map is used to replace all symbols of char array type in the axioms that are added using the parent method: supert::boolbv_set_equality_to_true. Defining several intermediary functions for check_axioms and cleaning. Check axioms is quite complicated so we splitted it in several parts. Avoid using same universal variable name in string comparison function. Corrected test in index_of as characters could be signed Corrected return type retrieval in from_float functions. The return type should be given as argument of the helper function add_axioms_from_float. Fixed type of contains in constraint generation Introduce string_refinementt::set_to. We now override the set_to() method instead of set_equality_to_true(). This solves a problem where many lemmas were being dropped. Handle array_of in set_char_array_equality. Java assignments such as char[] str=new char[10] involves assigning the char array to 0, which is done using the array_of operator. This operator is now handled when found on the rhs of a char array assignment. Optimized string hash code and intern functions to only look at seen strings. We only compare the argument to the strings on which hash_code (resp. intern) was already called. Add missing override keyword in declarations Integrate strings into symbol resolution. We now use for strings the mechanism that was made for resolving symbols to char arrays. As a result, the symbol_to_string map has been removed. We introduce an unresolved_symbol map to associate symbols to string expressions that were introduced during constraint generation. Preventing return of nil exprt in sum_over_map Enforce -1 for witnesses when strings are unequal. This makes it easier to see when models for string have different length. Correct array index in get_array Correct a bad array access that caused a segmentation fault on the java_delete test. Adding option to concretize result and get method in string solver The option to concretize makes sure that the model that we get in the end is correct. Overiding the get method is necessary to get the actual valuation of string gotten by the solver. This two additions makes the trace generation for program with strings more likely to be actual traces of the program. Avoid adding axioms for copy Corrected `get` to not replace strings Simplifying lemmas before handing them to the solver This seems to improve performances Ignoring char array that are not symbol or constants Avoid creating new length variable for concat Adding constraint on positive length for refined strings Using get method of the parent class for the size Add function to fill the found_length map Signature for get_array should be constant Corrected overflow problem when integer get to the max size Removing overflow check in universal constraint Enforcing witness -1 when length is not sufficient in suffix Corrected index variable which should be universally quantified Factorizing addition to index set and more debug information Avoiding generating a fresh string for the empty string Enabling string solver to treat more cases and more debug infos Conversion from char pointer to array in the solver Raise a warning if found length is negative Ensure the arguments of parseInt are of the right format For now we add axioms asking for the argument to have the right format but ultimately we should raise an exception when it is not the case (which is not done right now). Corrects the specification of int to string conversion Some problems where encountered for strings with the maximal size possible for an int, which could cause an overflow. Disallow + sign in string from int Java will not add the sign for positive numbers Use get instead of current_model in check_axioms Streamline code of check_axioms() by calling get() insteand of relying on the 'current_model' variable. get() has been adapted to convert array-lists into with expressions, the former not being handled by the string solver. --- src/solvers/refinement/string_constraint.h | 1 - .../refinement/string_constraint_generator.h | 45 +- ...tring_constraint_generator_code_points.cpp | 18 +- ...string_constraint_generator_comparison.cpp | 102 +- .../string_constraint_generator_concat.cpp | 31 +- .../string_constraint_generator_constants.cpp | 9 +- .../string_constraint_generator_indexof.cpp | 27 +- .../string_constraint_generator_insert.cpp | 24 +- .../string_constraint_generator_main.cpp | 422 +++++--- .../string_constraint_generator_testing.cpp | 46 +- ...ng_constraint_generator_transformation.cpp | 39 +- .../string_constraint_generator_valueof.cpp | 101 +- src/solvers/refinement/string_refinement.cpp | 917 ++++++++++++++---- src/solvers/refinement/string_refinement.h | 66 +- 14 files changed, 1323 insertions(+), 525 deletions(-) diff --git a/src/solvers/refinement/string_constraint.h b/src/solvers/refinement/string_constraint.h index 4b8d1229e09..1bb460349b7 100644 --- a/src/solvers/refinement/string_constraint.h +++ b/src/solvers/refinement/string_constraint.h @@ -48,7 +48,6 @@ class string_constraintt: public exprt return operands()[4]; } - private: string_constraintt(); diff --git a/src/solvers/refinement/string_constraint_generator.h b/src/solvers/refinement/string_constraint_generator.h index ed898cb9a18..12447e0cf04 100644 --- a/src/solvers/refinement/string_constraint_generator.h +++ b/src/solvers/refinement/string_constraint_generator.h @@ -14,6 +14,7 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com #define CPROVER_SOLVERS_REFINEMENT_STRING_CONSTRAINT_GENERATOR_H #include +#include #include #include @@ -65,21 +66,20 @@ class string_constraint_generatort symbol_exprt fresh_univ_index(const irep_idt &prefix, const typet &type); symbol_exprt fresh_boolean(const irep_idt &prefix); string_exprt fresh_string(const refined_string_typet &type); + string_exprt get_string_expr(const exprt &expr); + string_exprt convert_java_string_to_string_exprt( + const exprt &underlying); + plus_exprt plus_exprt_with_overflow_check(const exprt &op1, const exprt &op2); - // We maintain a map from symbols to strings. - std::map symbol_to_string; + // Maps unresolved symbols to the string_exprt that was created for them + std::map unresolved_symbols; - string_exprt find_or_add_string_of_symbol(const symbol_exprt &sym); - void assign_to_symbol( - const symbol_exprt &sym, const string_exprt &expr) - { - symbol_to_string[sym.get_identifier()]=expr; - } + string_exprt find_or_add_string_of_symbol( + const symbol_exprt &sym, + const refined_string_typet &ref_type); - string_exprt add_axioms_for_string_expr(const exprt &expr); - void set_string_symbol_equal_to_expr( - const symbol_exprt &sym, const exprt &str); + string_exprt add_axioms_for_refined_string(const exprt &expr); exprt add_axioms_for_function_application( const function_application_exprt &expr); @@ -96,6 +96,8 @@ class string_constraint_generatort const std::size_t MAX_FLOAT_LENGTH=15; const std::size_t MAX_DOUBLE_LENGTH=30; + std::map function_application_cache; + static irep_idt extract_java_string(const symbol_exprt &s); exprt axiom_for_is_positive_index(const exprt &x); @@ -117,6 +119,9 @@ class string_constraint_generatort // The specification is partial: the actual value is not actually computed // but we ensure that hash codes of equal strings are equal. exprt add_axioms_for_hash_code(const function_application_exprt &f); + // To each string on which hash_code was called we associate a symbol + // representing the return value of the hash_code function. + std::map hash_code_of_string; exprt add_axioms_for_is_empty(const function_application_exprt &f); exprt add_axioms_for_is_prefix( @@ -224,7 +229,9 @@ class string_constraint_generatort // the start for negative number string_exprt add_axioms_from_float(const function_application_exprt &f); string_exprt add_axioms_from_float( - const exprt &f, bool double_precision=false); + const exprt &f, + const refined_string_typet &ref_type, + bool double_precision); // Add axioms corresponding to the String.valueOf(D) java function // TODO: the specifications is only partial @@ -253,6 +260,7 @@ class string_constraint_generatort string_exprt add_axioms_for_code_point( const exprt &code_point, const refined_string_typet &ref_type); string_exprt add_axioms_for_java_char_array(const exprt &char_array); + exprt add_axioms_for_char_pointer(const function_application_exprt &fun); string_exprt add_axioms_for_if(const if_exprt &expr); exprt add_axioms_for_char_literal(const function_application_exprt &f); @@ -270,6 +278,8 @@ class string_constraint_generatort const function_application_exprt &f); exprt add_axioms_for_parse_int(const function_application_exprt &f); + exprt add_axioms_for_correct_number_format( + const string_exprt &str, std::size_t max_size=10); exprt add_axioms_for_to_char_array(const function_application_exprt &f); exprt add_axioms_for_compare_to(const function_application_exprt &f); @@ -278,6 +288,9 @@ class string_constraint_generatort // string pointers symbol_exprt add_axioms_for_intern(const function_application_exprt &f); + // Pool used for the intern method + std::map intern_of_string; + // Tells which language is used. C and Java are supported irep_idt mode; @@ -293,14 +306,8 @@ class string_constraint_generatort exprt int_of_hex_char(const exprt &chr) const; exprt is_high_surrogate(const exprt &chr) const; exprt is_low_surrogate(const exprt &chr) const; - static exprt character_equals_ignore_case( + exprt character_equals_ignore_case( exprt char1, exprt char2, exprt char_a, exprt char_A, exprt char_Z); - - // Pool used for the intern method - std::map pool; - - // Used to determine whether hashcode should be equal - std::map hash; }; #endif diff --git a/src/solvers/refinement/string_constraint_generator_code_points.cpp b/src/solvers/refinement/string_constraint_generator_code_points.cpp index 7c035a0d3e4..16763dfc97c 100644 --- a/src/solvers/refinement/string_constraint_generator_code_points.cpp +++ b/src/solvers/refinement/string_constraint_generator_code_points.cpp @@ -160,17 +160,18 @@ exprt string_constraint_generatort::add_axioms_for_code_point_at( { typet return_type=f.type(); assert(return_type.id()==ID_signedbv); - string_exprt str=add_axioms_for_string_expr(args(f, 2)[0]); + string_exprt str=get_string_expr(args(f, 2)[0]); const exprt &pos=args(f, 2)[1]; symbol_exprt result=fresh_symbol("char", return_type); exprt index1=from_integer(1, str.length().type()); const exprt &char1=str[pos]; - const exprt &char2=str[plus_exprt(pos, index1)]; + const exprt &char2=str[plus_exprt_with_overflow_check(pos, index1)]; exprt char1_as_int=typecast_exprt(char1, return_type); exprt char2_as_int=typecast_exprt(char2, return_type); exprt pair=pair_value(char1_as_int, char2_as_int, return_type); - exprt is_low=is_low_surrogate(str[plus_exprt(pos, index1)]); + exprt is_low=is_low_surrogate( + str[plus_exprt_with_overflow_check(pos, index1)]); exprt return_pair=and_exprt(is_high_surrogate(str[pos]), is_low); axioms.push_back(implies_exprt(return_pair, equal_exprt(result, pair))); @@ -199,7 +200,7 @@ exprt string_constraint_generatort::add_axioms_for_code_point_before( typet return_type=f.type(); assert(return_type.id()==ID_signedbv); symbol_exprt result=fresh_symbol("char", return_type); - string_exprt str=add_axioms_for_string_expr(args[0]); + string_exprt str=get_string_expr(args[0]); const exprt &char1= str[minus_exprt(args[1], from_integer(2, str.length().type()))]; @@ -234,7 +235,7 @@ Function: string_constraint_generatort::add_axioms_for_code_point_count exprt string_constraint_generatort::add_axioms_for_code_point_count( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 3)[0]); + string_exprt str=get_string_expr(args(f, 3)[0]); const exprt &begin=args(f, 3)[1]; const exprt &end=args(f, 3)[2]; const typet &return_type=f.type(); @@ -265,14 +266,15 @@ Function: string_constraint_generatort::add_axioms_for_offset_by_code_point exprt string_constraint_generatort::add_axioms_for_offset_by_code_point( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 3)[0]); + string_exprt str=get_string_expr(args(f, 3)[0]); const exprt &index=args(f, 3)[1]; const exprt &offset=args(f, 3)[2]; const typet &return_type=f.type(); symbol_exprt result=fresh_symbol("offset_by_code_point", return_type); - exprt minimum=plus_exprt(index, offset); - exprt maximum=plus_exprt(index, plus_exprt(offset, offset)); + exprt minimum=plus_exprt_with_overflow_check(index, offset); + exprt maximum=plus_exprt_with_overflow_check( + index, plus_exprt_with_overflow_check(offset, offset)); axioms.push_back(binary_relation_exprt(result, ID_le, maximum)); axioms.push_back(binary_relation_exprt(result, ID_ge, minimum)); diff --git a/src/solvers/refinement/string_constraint_generator_comparison.cpp b/src/solvers/refinement/string_constraint_generator_comparison.cpp index 321282ee9c1..a51e2abe3cd 100644 --- a/src/solvers/refinement/string_constraint_generator_comparison.cpp +++ b/src/solvers/refinement/string_constraint_generator_comparison.cpp @@ -18,7 +18,9 @@ Function: string_constraint_generatort::add_axioms_for_equals Outputs: a expression of Boolean type Purpose: add axioms stating that the result is true exactly when the strings - represented by the arguments are equal + represented by the arguments are equal. + the variable ending in `witness_unequal` is -1 if the length differs + or an index at which the strings are different \*******************************************************************/ @@ -29,8 +31,8 @@ exprt string_constraint_generatort::add_axioms_for_equals( symbol_exprt eq=fresh_boolean("equal"); typecast_exprt tc_eq(eq, f.type()); - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); - string_exprt s2=add_axioms_for_string_expr(args(f, 2)[1]); + string_exprt s1=get_string_expr(args(f, 2)[0]); + string_exprt s2=get_string_expr(args(f, 2)[1]); typet index_type=s1.length().type(); // We want to write: @@ -54,9 +56,10 @@ exprt string_constraint_generatort::add_axioms_for_equals( binary_relation_exprt(witness, ID_lt, s1.length()), binary_relation_exprt(witness, ID_ge, zero)); and_exprt witnessing(bound_witness, notequal_exprt(s1[witness], s2[witness])); - implies_exprt a3( - not_exprt(eq), - or_exprt(notequal_exprt(s1.length(), s2.length()), witnessing)); + and_exprt diff_length( + notequal_exprt(s1.length(), s2.length()), + equal_exprt(witness, from_integer(-1, index_type))); + implies_exprt a3(not_exprt(eq), or_exprt(diff_length, witnessing)); axioms.push_back(a3); return tc_eq; @@ -92,8 +95,13 @@ exprt string_constraint_generatort::character_equals_ignore_case( // p3 : (is_up2&&'a'-'A'+char2=char1) equal_exprt p1(char1, char2); minus_exprt diff=minus_exprt(char_a, char_A); - and_exprt p2(is_upper_case_1, equal_exprt(plus_exprt(diff, char1), char2)); - and_exprt p3(is_upper_case_2, equal_exprt(plus_exprt(diff, char2), char1)); + + // Overflow is not a problem here because is_upper_case conditions + // ensure that we are within a safe range. + and_exprt p2(is_upper_case_1, + equal_exprt(plus_exprt(diff, char1), char2)); + and_exprt p3(is_upper_case_2, + equal_exprt(plus_exprt(diff, char2), char1)); return or_exprt(or_exprt(p1, p2), p3); } @@ -116,8 +124,8 @@ exprt string_constraint_generatort::add_axioms_for_equals_ignore_case( symbol_exprt eq=fresh_boolean("equal_ignore_case"); typecast_exprt tc_eq(eq, f.type()); - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); - string_exprt s2=add_axioms_for_string_expr(args(f, 2)[1]); + string_exprt s1=get_string_expr(args(f, 2)[0]); + string_exprt s2=get_string_expr(args(f, 2)[1]); typet char_type=to_refined_string_type(s1.type()).get_char_type(); exprt char_a=constant_char('a', char_type); exprt char_A=constant_char('A', char_type); @@ -174,37 +182,35 @@ Function: string_constraint_generatort::add_axioms_for_hash_code exprt string_constraint_generatort::add_axioms_for_hash_code( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 1)[0]); + string_exprt str=get_string_expr(args(f, 1)[0]); typet return_type=f.type(); typet index_type=str.length().type(); - // initialisation of the missing pool variable - std::map::iterator it; - for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++) - if(hash.find(it->second)==hash.end()) - hash[it->second]=fresh_symbol("hash", return_type); + auto pair=hash_code_of_string.insert( + std::make_pair(str, fresh_symbol("hash", return_type))); + exprt hash=pair.first->second; // for each string s. either: // c1: hash(str)=hash(s) // c2: |str|!=|s| - // c3: (|str|==|s| &&exists i<|s|. s[i]!=str[i]) + // c3: (|str|==|s| && exists i<|s|. s[i]!=str[i]) // WARNING: the specification may be incomplete - for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++) + for(auto it : hash_code_of_string) { symbol_exprt i=fresh_exist_index("index_hash", index_type); - equal_exprt c1(hash[it->second], hash[str]); - not_exprt c2(equal_exprt(it->second.length(), str.length())); + equal_exprt c1(it.second, hash); + not_exprt c2(equal_exprt(it.first.length(), str.length())); and_exprt c3( - equal_exprt(it->second.length(), str.length()), + equal_exprt(it.first.length(), str.length()), and_exprt( - not_exprt(equal_exprt(str[i], it->second[i])), + not_exprt(equal_exprt(str[i], it.first[i])), and_exprt( str.axiom_for_is_strictly_longer_than(i), axiom_for_is_positive_index(i)))); axioms.push_back(or_exprt(c1, or_exprt(c2, c3))); } - return hash[str]; + return hash; } /*******************************************************************\ @@ -222,8 +228,8 @@ Function: string_constraint_generatort::add_axioms_for_compare_to exprt string_constraint_generatort::add_axioms_for_compare_to( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); - string_exprt s2=add_axioms_for_string_expr(args(f, 2)[1]); + string_exprt s1=get_string_expr(args(f, 2)[0]); + string_exprt s2=get_string_expr(args(f, 2)[1]); const typet &return_type=f.type(); symbol_exprt res=fresh_symbol("compare_to", return_type); typet index_type=s1.length().type(); @@ -234,12 +240,12 @@ exprt string_constraint_generatort::add_axioms_for_compare_to( // a1 : res==0 => |s1|=|s2| // a2 : forall i<|s1|. s1[i]==s2[i] // a3 : exists x. - // res!=0 ==> x> 0 && - // ((|s1| <= |s2| &&x<|s1|) || (|s1| >= |s2| &&x<|s2|) - // &&res=s1[x]-s2[x] ) - // || cond2: - // (|s1|<|s2| &&x=|s1|) || (|s1| > |s2| &&x=|s2|) &&res=|s1|-|s2|) - // a4 : forall i s1[i]=s2[i] + // res!=0 ==> x > 0 + // && ((|s1| <= |s2| && x<|s1|) || (|s1| >= |s2| &&x<|s2|) + // && res=s1[x]-s2[x] ) + // || cond2: + // (|s1|<|s2| &&x=|s1|) || (|s1| > |s2| &&x=|s2|) &&res=|s1|-|s2|) + // a4 : forall i' s1[i]=s2[i] assert(return_type.id()==ID_signedbv); @@ -282,7 +288,9 @@ exprt string_constraint_generatort::add_axioms_for_compare_to( or_exprt(cond1, cond2))); axioms.push_back(a3); - string_constraintt a4(i, x, not_exprt(res_null), equal_exprt(s1[i], s2[i])); + symbol_exprt i2=fresh_univ_index("QA_compare_to", index_type); + string_constraintt a4( + i2, x, not_exprt(res_null), equal_exprt(s1[i2], s2[i2])); axioms.push_back(a4); return res; @@ -304,15 +312,15 @@ Function: string_constraint_generatort::add_axioms_for_intern symbol_exprt string_constraint_generatort::add_axioms_for_intern( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 1)[0]); + string_exprt str=get_string_expr(args(f, 1)[0]); + // For now we only enforce content equality and not pointer equality const typet &return_type=f.type(); + typet index_type=str.length().type(); - // initialisation of the missing pool variable - std::map::iterator it; - for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++) - if(pool.find(it->second)==pool.end()) - pool[it->second]=fresh_symbol("pool", return_type); + auto pair=intern_of_string.insert( + std::make_pair(str, fresh_symbol("pool", return_type))); + symbol_exprt intern=pair.first->second; // intern(str)=s_0 || s_1 || ... // for each string s. @@ -320,30 +328,30 @@ symbol_exprt string_constraint_generatort::add_axioms_for_intern( // || (|str|==|s| &&exists i<|s|. s[i]!=str[i]) exprt disj=false_exprt(); - for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++) + for(auto it : intern_of_string) disj=or_exprt( - disj, equal_exprt(pool[str], symbol_exprt(it->first, return_type))); + disj, equal_exprt(intern, it.second)); axioms.push_back(disj); // WARNING: the specification may be incomplete or incorrect - for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++) - if(it->second!=str) + for(auto it : intern_of_string) + if(it.second!=str) { symbol_exprt i=fresh_exist_index("index_intern", index_type); axioms.push_back( or_exprt( - equal_exprt(pool[it->second], pool[str]), + equal_exprt(it.second, intern), or_exprt( - not_exprt(str.axiom_for_has_same_length_as(it->second)), + not_exprt(str.axiom_for_has_same_length_as(it.first)), and_exprt( - str.axiom_for_has_same_length_as(it->second), + str.axiom_for_has_same_length_as(it.first), and_exprt( - not_exprt(equal_exprt(str[i], it->second[i])), + not_exprt(equal_exprt(str[i], it.first[i])), and_exprt(str.axiom_for_is_strictly_longer_than(i), axiom_for_is_positive_index(i))))))); } - return pool[str]; + return intern; } diff --git a/src/solvers/refinement/string_constraint_generator_concat.cpp b/src/solvers/refinement/string_constraint_generator_concat.cpp index a7d9c4921c4..fb8e24d5320 100644 --- a/src/solvers/refinement/string_constraint_generator_concat.cpp +++ b/src/solvers/refinement/string_constraint_generator_concat.cpp @@ -35,9 +35,7 @@ string_exprt string_constraint_generatort::add_axioms_for_concat( // a4 : forall i<|s1|. res[i]=s1[i] // a5 : forall i<|s2|. res[i+|s1|]=s2[i] - exprt a1=res.axiom_for_has_length( - plus_exprt(s1.length(), s2.length())); - axioms.push_back(a1); + res.length()=plus_exprt_with_overflow_check(s1.length(), s2.length()); axioms.push_back(s1.axiom_for_is_shorter_than(res)); axioms.push_back(s2.axiom_for_is_shorter_than(res)); @@ -73,8 +71,8 @@ string_exprt string_constraint_generatort::add_axioms_for_concat( const function_application_exprt::argumentst &args=f.arguments(); assert(args.size()==2); - string_exprt s1=add_axioms_for_string_expr(args[0]); - string_exprt s2=add_axioms_for_string_expr(args[1]); + string_exprt s1=get_string_expr(args[0]); + string_exprt s2=get_string_expr(args[1]); return add_axioms_for_concat(s1, s2); } @@ -95,7 +93,7 @@ string_exprt string_constraint_generatort::add_axioms_for_concat_int( const function_application_exprt &f) { const refined_string_typet &ref_type=to_refined_string_type(f.type()); - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); + string_exprt s1=get_string_expr(args(f, 2)[0]); string_exprt s2=add_axioms_from_int( args(f, 2)[1], MAX_INTEGER_LENGTH, ref_type); return add_axioms_for_concat(s1, s2); @@ -118,7 +116,7 @@ string_exprt string_constraint_generatort::add_axioms_for_concat_long( const function_application_exprt &f) { const refined_string_typet &ref_type=to_refined_string_type(f.type()); - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); + string_exprt s1=get_string_expr(args(f, 2)[0]); string_exprt s2=add_axioms_from_int(args(f, 2)[1], MAX_LONG_LENGTH, ref_type); return add_axioms_for_concat(s1, s2); } @@ -138,7 +136,7 @@ Function: string_constraint_generatort::add_axioms_for_concat_bool string_exprt string_constraint_generatort::add_axioms_for_concat_bool( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); + string_exprt s1=get_string_expr(args(f, 2)[0]); const refined_string_typet &ref_type=to_refined_string_type(s1.type()); string_exprt s2=add_axioms_from_bool(args(f, 2)[1], ref_type); return add_axioms_for_concat(s1, s2); @@ -159,7 +157,7 @@ Function: string_constraint_generatort::add_axioms_for_concat_char string_exprt string_constraint_generatort::add_axioms_for_concat_char( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); + string_exprt s1=get_string_expr(args(f, 2)[0]); const refined_string_typet &ref_type=to_refined_string_type(s1.type()); string_exprt s2=add_axioms_from_char(args(f, 2)[1], ref_type); return add_axioms_for_concat(s1, s2); @@ -180,9 +178,10 @@ Function: string_constraint_generatort::add_axioms_for_concat_double string_exprt string_constraint_generatort::add_axioms_for_concat_double( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); - string_exprt s2=add_axioms_from_float( - args(f, 2)[1], MAX_DOUBLE_LENGTH); + string_exprt s1=get_string_expr(args(f, 2)[0]); + assert(refined_string_typet::is_refined_string_type(f.type())); + refined_string_typet ref_type=to_refined_string_type(f.type()); + string_exprt s2=add_axioms_from_float(args(f, 2)[1], ref_type, true); return add_axioms_for_concat(s1, s2); } @@ -201,8 +200,10 @@ Function: string_constraint_generatort::add_axioms_for_concat_float string_exprt string_constraint_generatort::add_axioms_for_concat_float( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); - string_exprt s2=add_axioms_from_float(args(f, 2)[1], MAX_FLOAT_LENGTH); + string_exprt s1=get_string_expr(args(f, 2)[0]); + assert(refined_string_typet::is_refined_string_type(f.type())); + refined_string_typet ref_type=to_refined_string_type(f.type()); + string_exprt s2=add_axioms_from_float(args(f, 2)[1], ref_type, false); return add_axioms_for_concat(s1, s2); } @@ -222,7 +223,7 @@ Function: string_constraint_generatort::add_axioms_for_concat_code_point string_exprt string_constraint_generatort::add_axioms_for_concat_code_point( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); + string_exprt s1=get_string_expr(args(f, 2)[0]); const refined_string_typet &ref_type=to_refined_string_type(s1.type()); string_exprt s2=add_axioms_for_code_point(args(f, 2)[1], ref_type); return add_axioms_for_concat(s1, s2); diff --git a/src/solvers/refinement/string_constraint_generator_constants.cpp b/src/solvers/refinement/string_constraint_generator_constants.cpp index 64ffabfd266..2905c6a5f21 100644 --- a/src/solvers/refinement/string_constraint_generator_constants.cpp +++ b/src/solvers/refinement/string_constraint_generator_constants.cpp @@ -93,9 +93,13 @@ string_exprt string_constraint_generatort::add_axioms_for_empty_string( const function_application_exprt &f) { assert(f.arguments().empty()); + assert(refined_string_typet::is_refined_string_type(f.type())); const refined_string_typet &ref_type=to_refined_string_type(f.type()); - string_exprt res=fresh_string(ref_type); - axioms.push_back(res.axiom_for_has_length(0)); + exprt size=from_integer(0, ref_type.get_index_type()); + const array_typet &content_type=ref_type.get_content_type(); + array_of_exprt empty_array( + from_integer(0, ref_type.get_content_type().subtype()), content_type); + string_exprt res(size, empty_array, ref_type); return res; } @@ -132,6 +136,7 @@ string_exprt string_constraint_generatort::add_axioms_from_literal( else { // Java string constant + assert(false); // TODO: Check if used. On the contrary, discard else. assert(arg.id()==ID_symbol); const exprt &s=arg.op0(); diff --git a/src/solvers/refinement/string_constraint_generator_indexof.cpp b/src/solvers/refinement/string_constraint_generator_indexof.cpp index 283de683bd6..d799091a573 100644 --- a/src/solvers/refinement/string_constraint_generator_indexof.cpp +++ b/src/solvers/refinement/string_constraint_generator_indexof.cpp @@ -92,15 +92,16 @@ exprt string_constraint_generatort::add_axioms_for_index_of_string( symbol_exprt contains=fresh_boolean("contains_substring"); // We add axioms: - // a1 : contains => |substring|>=offset>=from_index + // a1 : contains => |str|-|substring|>=offset>=from_index // a2 : !contains => offset=-1 - // a3 : forall 0 <= witness str[witness+offset]=substring[witness] + // a3 : forall 0<=witness<|substring|. + // contains => str[witness+offset]=substring[witness] implies_exprt a1( contains, and_exprt( - str.axiom_for_is_longer_than(plus_exprt(substring.length(), offset)), + str.axiom_for_is_longer_than(plus_exprt_with_overflow_check( + substring.length(), offset)), binary_relation_exprt(offset, ID_ge, from_index))); axioms.push_back(a1); @@ -138,7 +139,8 @@ exprt string_constraint_generatort::add_axioms_for_last_index_of_string( implies_exprt a1( contains, and_exprt( - str.axiom_for_is_longer_than(plus_exprt(substring.length(), offset)), + str.axiom_for_is_longer_than( + plus_exprt_with_overflow_check(substring.length(), offset)), binary_relation_exprt(offset, ID_le, from_index))); axioms.push_back(a1); @@ -173,7 +175,7 @@ exprt string_constraint_generatort::add_axioms_for_index_of( const function_application_exprt &f) { const function_application_exprt::argumentst &args=f.arguments(); - string_exprt str=add_axioms_for_string_expr(args[0]); + string_exprt str=get_string_expr(args[0]); const exprt &c=args[1]; const refined_string_typet &ref_type=to_refined_string_type(str.type()); assert(f.type()==ref_type.get_index_type()); @@ -186,14 +188,15 @@ exprt string_constraint_generatort::add_axioms_for_index_of( else assert(false); - if(c.type().id()==ID_unsignedbv) + if(c.type().id()==ID_unsignedbv || c.type().id()==ID_signedbv) { return add_axioms_for_index_of( str, typecast_exprt(c, ref_type.get_char_type()), from_index); } else { - string_exprt sub=add_axioms_for_string_expr(c); + assert(refined_string_typet::is_refined_string_type(c.type())); + string_exprt sub=get_string_expr(c); return add_axioms_for_index_of_string(str, sub, from_index); } } @@ -215,7 +218,7 @@ exprt string_constraint_generatort::add_axioms_for_last_index_of( exprt index1=from_integer(1, index_type); exprt minus1=from_integer(-1, index_type); - exprt from_index_plus_one=plus_exprt(from_index, index1); + exprt from_index_plus_one=plus_exprt_with_overflow_check(from_index, index1); and_exprt a1( binary_relation_exprt(index, ID_ge, minus1), binary_relation_exprt(index, ID_lt, from_index_plus_one)); @@ -269,7 +272,7 @@ exprt string_constraint_generatort::add_axioms_for_last_index_of( const function_application_exprt &f) { const function_application_exprt::argumentst &args=f.arguments(); - string_exprt str=add_axioms_for_string_expr(args[0]); + string_exprt str=get_string_expr(args[0]); exprt c=args[1]; const refined_string_typet &ref_type=to_refined_string_type(str.type()); exprt from_index; @@ -282,14 +285,14 @@ exprt string_constraint_generatort::add_axioms_for_last_index_of( else assert(false); - if(c.type().id()==ID_unsignedbv) + if(c.type().id()==ID_unsignedbv || c.type().id()==ID_signedbv) { return add_axioms_for_last_index_of( str, typecast_exprt(c, ref_type.get_char_type()), from_index); } else { - string_exprt sub=add_axioms_for_string_expr(c); + string_exprt sub=get_string_expr(c); return add_axioms_for_last_index_of_string(str, sub, from_index); } } diff --git a/src/solvers/refinement/string_constraint_generator_insert.cpp b/src/solvers/refinement/string_constraint_generator_insert.cpp index 6a080a5dc6c..cd5f4376a93 100644 --- a/src/solvers/refinement/string_constraint_generator_insert.cpp +++ b/src/solvers/refinement/string_constraint_generator_insert.cpp @@ -48,8 +48,8 @@ Function: string_constraint_generatort::add_axioms_for_insert string_exprt string_constraint_generatort::add_axioms_for_insert( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 3)[0]); - string_exprt s2=add_axioms_for_string_expr(args(f, 3)[2]); + string_exprt s1=get_string_expr(args(f, 3)[0]); + string_exprt s2=get_string_expr(args(f, 3)[2]); return add_axioms_for_insert(s1, s2, args(f, 3)[1]); } @@ -70,7 +70,7 @@ string_exprt string_constraint_generatort::add_axioms_for_insert_int( const function_application_exprt &f) { const refined_string_typet &ref_type=to_refined_string_type(f.type()); - string_exprt s1=add_axioms_for_string_expr(args(f, 3)[0]); + string_exprt s1=get_string_expr(args(f, 3)[0]); string_exprt s2=add_axioms_from_int( args(f, 3)[2], MAX_INTEGER_LENGTH, ref_type); return add_axioms_for_insert(s1, s2, args(f, 3)[1]); @@ -93,7 +93,7 @@ string_exprt string_constraint_generatort::add_axioms_for_insert_long( const function_application_exprt &f) { const refined_string_typet &ref_type=to_refined_string_type(f.type()); - string_exprt s1=add_axioms_for_string_expr(args(f, 3)[0]); + string_exprt s1=get_string_expr(args(f, 3)[0]); string_exprt s2=add_axioms_from_int(args(f, 3)[2], MAX_LONG_LENGTH, ref_type); return add_axioms_for_insert(s1, s2, args(f, 3)[1]); } @@ -115,7 +115,7 @@ string_exprt string_constraint_generatort::add_axioms_for_insert_bool( const function_application_exprt &f) { const refined_string_typet &ref_type=to_refined_string_type(f.type()); - string_exprt s1=add_axioms_for_string_expr(args(f, 3)[0]); + string_exprt s1=get_string_expr(args(f, 3)[0]); string_exprt s2=add_axioms_from_bool(args(f, 3)[2], ref_type); return add_axioms_for_insert(s1, s2, args(f, 3)[1]); } @@ -136,7 +136,7 @@ Function: string_constraint_generatort::add_axioms_for_insert_char string_exprt string_constraint_generatort::add_axioms_for_insert_char( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 3)[0]); + string_exprt s1=get_string_expr(args(f, 3)[0]); const refined_string_typet &ref_type=to_refined_string_type(s1.type()); string_exprt s2=add_axioms_from_char(args(f, 3)[2], ref_type); return add_axioms_for_insert(s1, s2, args(f, 3)[1]); @@ -158,8 +158,9 @@ Function: string_constraint_generatort::add_axioms_for_insert_double string_exprt string_constraint_generatort::add_axioms_for_insert_double( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 3)[0]); - string_exprt s2=add_axioms_from_float(args(f, 3)[2]); + string_exprt s1=get_string_expr(args(f, 3)[0]); + const refined_string_typet &ref_type=to_refined_string_type(s1.type()); + string_exprt s2=add_axioms_from_float(args(f, 3)[2], ref_type, true); return add_axioms_for_insert(s1, s2, args(f, 3)[1]); } @@ -179,8 +180,9 @@ Function: string_constraint_generatort::add_axioms_for_insert_float string_exprt string_constraint_generatort::add_axioms_for_insert_float( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 3)[0]); - string_exprt s2=add_axioms_from_float(args(f, 3)[2]); + string_exprt s1=get_string_expr(args(f, 3)[0]); + const refined_string_typet &ref_type=to_refined_string_type(s1.type()); + string_exprt s2=add_axioms_from_float(args(f, 3)[2], ref_type, false); return add_axioms_for_insert(s1, s2, args(f, 3)[1]); } @@ -216,7 +218,7 @@ string_exprt string_constraint_generatort::add_axioms_for_insert_char_array( offset=from_integer(0, count.type()); } - string_exprt str=add_axioms_for_string_expr(f.arguments()[0]); + string_exprt str=get_string_expr(f.arguments()[0]); const exprt &length=f.arguments()[2]; const exprt &data=f.arguments()[3]; string_exprt arr=add_axioms_from_char_array( diff --git a/src/solvers/refinement/string_constraint_generator_main.cpp b/src/solvers/refinement/string_constraint_generator_main.cpp index 7fe510c2e35..f8dedaab9a7 100644 --- a/src/solvers/refinement/string_constraint_generator_main.cpp +++ b/src/solvers/refinement/string_constraint_generator_main.cpp @@ -16,6 +16,7 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com #include #include #include +#include unsigned string_constraint_generatort::next_symbol_id=1; @@ -122,6 +123,42 @@ symbol_exprt string_constraint_generatort::fresh_boolean( /*******************************************************************\ +Function: string_constraint_generatort::plus_exprt_with_overflow_check + + Inputs: + op1 - First term of the sum + op2 - Second term of the sum + + Outputs: A plus expression representing the sum of the arguments + + Purpose: Create a plus expression while adding extra constraints to + axioms in order to prevent overflows. + +\*******************************************************************/ +plus_exprt string_constraint_generatort::plus_exprt_with_overflow_check( + const exprt &op1, const exprt &op2) +{ + plus_exprt sum(plus_exprt(op1, op2)); + + exprt zero=from_integer(0, op1.type()); + + binary_relation_exprt neg1(op1, ID_lt, zero); + binary_relation_exprt neg2(op2, ID_lt, zero); + binary_relation_exprt neg_sum(sum, ID_lt, zero); + + // We prevent overflows by adding the following constraint: + // If the signs of the two operands are the same, then the sign of the sum + // should also be the same. + implies_exprt no_overflow(equal_exprt(neg1, neg2), + equal_exprt(neg1, neg_sum)); + + axioms.push_back(no_overflow); + + return sum; +} + +/*******************************************************************\ + Function: string_constraint_generatort::fresh_string Inputs: a type for string @@ -144,59 +181,113 @@ string_exprt string_constraint_generatort::fresh_string( /*******************************************************************\ -Function: string_constraint_generatort::add_axioms_for_string_expr +Function: string_constraint_generatort::get_string_expr + + Inputs: an expression of refined string type + + Outputs: a string expression + + Purpose: casts an expression to a string expression, or fetches the + actual string_exprt in the case of a symbol. + +\*******************************************************************/ + +string_exprt string_constraint_generatort::get_string_expr(const exprt &expr) +{ + assert(refined_string_typet::is_refined_string_type(expr.type())); + + if(expr.id()==ID_symbol) + { + return find_or_add_string_of_symbol( + to_symbol_expr(expr), + to_refined_string_type(expr.type())); + } + else + { + return to_string_expr(expr); + } +} + +string_exprt string_constraint_generatort::convert_java_string_to_string_exprt( + const exprt &jls) +{ + assert(get_mode()==ID_java); + assert(jls.id()==ID_struct); + + exprt length(to_struct_expr(jls).op1()); + // TODO: Add assertion on the type. + // assert(length.type()==refined_string_typet::index_type()); + exprt java_content(to_struct_expr(jls).op2()); + if(java_content.id()==ID_address_of) + { + java_content=to_address_of_expr(java_content).object(); + } + else + { + java_content=dereference_exprt(java_content, java_content.type()); + } + + refined_string_typet type(java_int_type(), java_char_type()); + + return string_exprt(length, java_content, type); +} + +/*******************************************************************\ + +Function: string_constraint_generatort::add_axioms_for_refined_string - Inputs: an expression of type string + Inputs: an expression of refined string type Outputs: a string expression that is linked to the argument through axioms that are added to the list - Purpose: obtain a refined string expression corresponding to string - variable of string function call + Purpose: obtain a refined string expression corresponding to a expression + of type string \*******************************************************************/ -string_exprt string_constraint_generatort::add_axioms_for_string_expr( - const exprt &unrefined_string) + +string_exprt string_constraint_generatort::add_axioms_for_refined_string( + const exprt &string) { - string_exprt s; + assert(refined_string_typet::is_refined_string_type(string.type())); + refined_string_typet type=to_refined_string_type(string.type()); - if(unrefined_string.id()==ID_function_application) + // Function applications should have been removed before + assert(string.id()!=ID_function_application); + + if(string.id()==ID_symbol) { - exprt res=add_axioms_for_function_application( - to_function_application_expr(unrefined_string)); - s=to_string_expr(res); + const symbol_exprt &sym=to_symbol_expr(string); + string_exprt s=find_or_add_string_of_symbol(sym, type); + axioms.push_back( + s.axiom_for_is_longer_than(from_integer(0, s.length().type()))); + return s; } - else if(unrefined_string.id()==ID_symbol) - s=find_or_add_string_of_symbol(to_symbol_expr(unrefined_string)); - else if(unrefined_string.id()==ID_address_of) + else if(string.id()==ID_nondet_symbol) { - assert(unrefined_string.op0().id()==ID_symbol); - s=find_or_add_string_of_symbol(to_symbol_expr(unrefined_string.op0())); + string_exprt s=fresh_string(type); + axioms.push_back( + s.axiom_for_is_longer_than(from_integer(0, s.length().type()))); + return s; } - else if(unrefined_string.id()==ID_if) - s=add_axioms_for_if(to_if_expr(unrefined_string)); - else if(unrefined_string.id()==ID_nondet_symbol || - unrefined_string.id()==ID_struct) + else if(string.id()==ID_if) { - // TODO: for now we ignore non deterministic symbols and struct + return add_axioms_for_if(to_if_expr(string)); } - else if(unrefined_string.id()==ID_typecast) + else if(string.id()==ID_struct) { - exprt arg=to_typecast_expr(unrefined_string).op(); - exprt res=add_axioms_for_string_expr(arg); - s=to_string_expr(res); + const string_exprt &s=to_string_expr(string); + axioms.push_back( + s.axiom_for_is_longer_than(from_integer(0, s.length().type()))); + return s; } else { - throw "add_axioms_for_string_expr:\n"+unrefined_string.pretty()+ + throw "add_axioms_for_refined_string:\n"+string.pretty()+ "\nwhich is not a function application, "+ - "a symbol or an if expression"; + "a symbol, a struct or an if expression"; } - - axioms.push_back( - s.axiom_for_is_longer_than(from_integer(0, s.length().type()))); - return s; } /*******************************************************************\ @@ -216,10 +307,10 @@ string_exprt string_constraint_generatort::add_axioms_for_if( { assert( refined_string_typet::is_refined_string_type(expr.true_case().type())); - string_exprt t=add_axioms_for_string_expr(expr.true_case()); + string_exprt t=get_string_expr(expr.true_case()); assert( refined_string_typet::is_refined_string_type(expr.false_case().type())); - string_exprt f=add_axioms_for_string_expr(expr.false_case()); + string_exprt f=get_string_expr(expr.false_case()); const refined_string_typet &ref_type=to_refined_string_type(t.type()); const typet &index_type=ref_type.get_index_type(); string_exprt res=fresh_string(ref_type); @@ -246,7 +337,7 @@ Function: string_constraint_generatort::find_or_add_string_of_symbol Outputs: a string expression - Purpose: if a symbol represent a string is present in the symbol_to_string + Purpose: if a symbol representing a string is present in the symbol_to_string table, returns the corresponding string, if the symbol is not yet present, creates a new string with the correct type depending on whether the mode is java or c, adds it to the table and returns it. @@ -254,12 +345,11 @@ Function: string_constraint_generatort::find_or_add_string_of_symbol \*******************************************************************/ string_exprt string_constraint_generatort::find_or_add_string_of_symbol( - const symbol_exprt &sym) + const symbol_exprt &sym, const refined_string_typet &ref_type) { irep_idt id=sym.get_identifier(); - const refined_string_typet &ref_type=to_refined_string_type(sym.type()); string_exprt str=fresh_string(ref_type); - auto entry=symbol_to_string.insert(std::make_pair(id, str)); + auto entry=unresolved_symbols.insert(std::make_pair(id, str)); return entry.first->second; } @@ -286,125 +376,180 @@ exprt string_constraint_generatort::add_axioms_for_function_application( const irep_idt &id=is_ssa_expr(name)?to_ssa_expr(name).get_object_name(): to_symbol_expr(name).get_identifier(); + std::string str_id(id.c_str()); + + size_t pos=str_id.find("func_length"); + if(pos!=std::string::npos) + { + function_application_exprt new_expr(expr); + // TODO: This part needs some improvement. + // Stripping the symbol name is not a very robust process. + new_expr.function() = symbol_exprt(str_id.substr(0, pos+4)); + assert(get_mode()==ID_java); + new_expr.type() = refined_string_typet(java_int_type(), java_char_type()); + + auto res_it=function_application_cache.insert(std::make_pair(new_expr, + nil_exprt())); + if(res_it.second) + { + string_exprt res=to_string_expr( + add_axioms_for_function_application(new_expr)); + res_it.first->second=res; + return res.length(); + } + else + return to_string_expr(res_it.first->second).length(); + } + + pos = str_id.find("func_data"); + if(pos!=std::string::npos) + { + function_application_exprt new_expr(expr); + new_expr.function() = symbol_exprt(str_id.substr(0, pos+4)); + new_expr.type() = refined_string_typet(java_int_type(), java_char_type()); + + auto res_it=function_application_cache.insert(std::make_pair(new_expr, + nil_exprt())); + if(res_it.second) + { + string_exprt res=to_string_expr( + add_axioms_for_function_application(new_expr)); + res_it.first->second=res; + return res.content(); + } + else + return to_string_expr(res_it.first->second).content(); + } + // TODO: improve efficiency of this test by either ordering test by frequency // or using a map + auto res_it=function_application_cache.find(expr); + if(res_it!=function_application_cache.end() && res_it->second!=nil_exprt()) + return res_it->second; + + exprt res; + if(id==ID_cprover_char_literal_func) - return add_axioms_for_char_literal(expr); + res=add_axioms_for_char_literal(expr); else if(id==ID_cprover_string_length_func) - return add_axioms_for_length(expr); + res=add_axioms_for_length(expr); else if(id==ID_cprover_string_equal_func) - return add_axioms_for_equals(expr); + res=add_axioms_for_equals(expr); else if(id==ID_cprover_string_equals_ignore_case_func) - return add_axioms_for_equals_ignore_case(expr); + res=add_axioms_for_equals_ignore_case(expr); else if(id==ID_cprover_string_is_empty_func) - return add_axioms_for_is_empty(expr); + res=add_axioms_for_is_empty(expr); else if(id==ID_cprover_string_char_at_func) - return add_axioms_for_char_at(expr); + res=add_axioms_for_char_at(expr); else if(id==ID_cprover_string_is_prefix_func) - return add_axioms_for_is_prefix(expr); + res=add_axioms_for_is_prefix(expr); else if(id==ID_cprover_string_is_suffix_func) - return add_axioms_for_is_suffix(expr); + res=add_axioms_for_is_suffix(expr); else if(id==ID_cprover_string_startswith_func) - return add_axioms_for_is_prefix(expr, true); + res=add_axioms_for_is_prefix(expr, true); else if(id==ID_cprover_string_endswith_func) - return add_axioms_for_is_suffix(expr, true); + res=add_axioms_for_is_suffix(expr, true); else if(id==ID_cprover_string_contains_func) - return add_axioms_for_contains(expr); + res=add_axioms_for_contains(expr); else if(id==ID_cprover_string_hash_code_func) - return add_axioms_for_hash_code(expr); + res=add_axioms_for_hash_code(expr); else if(id==ID_cprover_string_index_of_func) - return add_axioms_for_index_of(expr); + res=add_axioms_for_index_of(expr); else if(id==ID_cprover_string_last_index_of_func) - return add_axioms_for_last_index_of(expr); + res=add_axioms_for_last_index_of(expr); else if(id==ID_cprover_string_parse_int_func) - return add_axioms_for_parse_int(expr); + res=add_axioms_for_parse_int(expr); else if(id==ID_cprover_string_to_char_array_func) - return add_axioms_for_to_char_array(expr); + res=add_axioms_for_to_char_array(expr); else if(id==ID_cprover_string_code_point_at_func) - return add_axioms_for_code_point_at(expr); + res=add_axioms_for_code_point_at(expr); else if(id==ID_cprover_string_code_point_before_func) - return add_axioms_for_code_point_before(expr); + res=add_axioms_for_code_point_before(expr); else if(id==ID_cprover_string_code_point_count_func) - return add_axioms_for_code_point_count(expr); + res=add_axioms_for_code_point_count(expr); else if(id==ID_cprover_string_offset_by_code_point_func) - return add_axioms_for_offset_by_code_point(expr); + res=add_axioms_for_offset_by_code_point(expr); else if(id==ID_cprover_string_compare_to_func) - return add_axioms_for_compare_to(expr); + res=add_axioms_for_compare_to(expr); else if(id==ID_cprover_string_literal_func) - return add_axioms_from_literal(expr); + res=add_axioms_from_literal(expr); else if(id==ID_cprover_string_concat_func) - return add_axioms_for_concat(expr); + res=add_axioms_for_concat(expr); else if(id==ID_cprover_string_concat_int_func) - return add_axioms_for_concat_int(expr); + res=add_axioms_for_concat_int(expr); else if(id==ID_cprover_string_concat_long_func) - return add_axioms_for_concat_long(expr); + res=add_axioms_for_concat_long(expr); else if(id==ID_cprover_string_concat_bool_func) - return add_axioms_for_concat_bool(expr); + res=add_axioms_for_concat_bool(expr); else if(id==ID_cprover_string_concat_char_func) - return add_axioms_for_concat_char(expr); + res=add_axioms_for_concat_char(expr); else if(id==ID_cprover_string_concat_double_func) - return add_axioms_for_concat_double(expr); + res=add_axioms_for_concat_double(expr); else if(id==ID_cprover_string_concat_float_func) - return add_axioms_for_concat_float(expr); + res=add_axioms_for_concat_float(expr); else if(id==ID_cprover_string_concat_code_point_func) - return add_axioms_for_concat_code_point(expr); + res=add_axioms_for_concat_code_point(expr); else if(id==ID_cprover_string_insert_func) - return add_axioms_for_insert(expr); + res=add_axioms_for_insert(expr); else if(id==ID_cprover_string_insert_int_func) - return add_axioms_for_insert_int(expr); + res=add_axioms_for_insert_int(expr); else if(id==ID_cprover_string_insert_long_func) - return add_axioms_for_insert_long(expr); + res=add_axioms_for_insert_long(expr); else if(id==ID_cprover_string_insert_bool_func) - return add_axioms_for_insert_bool(expr); + res=add_axioms_for_insert_bool(expr); else if(id==ID_cprover_string_insert_char_func) - return add_axioms_for_insert_char(expr); + res=add_axioms_for_insert_char(expr); else if(id==ID_cprover_string_insert_double_func) - return add_axioms_for_insert_double(expr); + res=add_axioms_for_insert_double(expr); else if(id==ID_cprover_string_insert_float_func) - return add_axioms_for_insert_float(expr); + res=add_axioms_for_insert_float(expr); +#if 0 else if(id==ID_cprover_string_insert_char_array_func) - return add_axioms_for_insert_char_array(expr); + res=add_axioms_for_insert_char_array(expr); +#endif else if(id==ID_cprover_string_substring_func) - return add_axioms_for_substring(expr); + res=add_axioms_for_substring(expr); else if(id==ID_cprover_string_trim_func) - return add_axioms_for_trim(expr); + res=add_axioms_for_trim(expr); else if(id==ID_cprover_string_to_lower_case_func) - return add_axioms_for_to_lower_case(expr); + res=add_axioms_for_to_lower_case(expr); else if(id==ID_cprover_string_to_upper_case_func) - return add_axioms_for_to_upper_case(expr); + res=add_axioms_for_to_upper_case(expr); else if(id==ID_cprover_string_char_set_func) - return add_axioms_for_char_set(expr); + res=add_axioms_for_char_set(expr); else if(id==ID_cprover_string_value_of_func) - return add_axioms_for_value_of(expr); + res=add_axioms_for_value_of(expr); else if(id==ID_cprover_string_empty_string_func) - return add_axioms_for_empty_string(expr); + res=add_axioms_for_empty_string(expr); else if(id==ID_cprover_string_copy_func) - return add_axioms_for_copy(expr); + res=add_axioms_for_copy(expr); else if(id==ID_cprover_string_of_int_func) - return add_axioms_from_int(expr); + res=add_axioms_from_int(expr); else if(id==ID_cprover_string_of_int_hex_func) - return add_axioms_from_int_hex(expr); + res=add_axioms_from_int_hex(expr); else if(id==ID_cprover_string_of_float_func) - return add_axioms_from_float(expr); + res=add_axioms_from_float(expr); else if(id==ID_cprover_string_of_double_func) - return add_axioms_from_double(expr); + res=add_axioms_from_double(expr); else if(id==ID_cprover_string_of_long_func) - return add_axioms_from_long(expr); + res=add_axioms_from_long(expr); else if(id==ID_cprover_string_of_bool_func) - return add_axioms_from_bool(expr); + res=add_axioms_from_bool(expr); else if(id==ID_cprover_string_of_char_func) - return add_axioms_from_char(expr); - else if(id==ID_cprover_string_of_char_array_func) - return add_axioms_from_char_array(expr); + res=add_axioms_from_char(expr); else if(id==ID_cprover_string_set_length_func) - return add_axioms_for_set_length(expr); + res=add_axioms_for_set_length(expr); else if(id==ID_cprover_string_delete_func) - return add_axioms_for_delete(expr); + res=add_axioms_for_delete(expr); else if(id==ID_cprover_string_delete_char_at_func) - return add_axioms_for_delete_char_at(expr); + res=add_axioms_for_delete_char_at(expr); else if(id==ID_cprover_string_replace_func) - return add_axioms_for_replace(expr); + res=add_axioms_for_replace(expr); + else if(id==ID_cprover_string_intern_func) + res=add_axioms_for_intern(expr); + else if(id==ID_cprover_string_array_of_char_pointer_func) + res=add_axioms_for_char_pointer(expr); else { std::string msg( @@ -412,13 +557,16 @@ exprt string_constraint_generatort::add_axioms_for_function_application( msg+=id2string(id); throw msg; } + function_application_cache[expr]=res; + return res; } /*******************************************************************\ Function: string_constraint_generatort::add_axioms_for_copy - Inputs: function application with one argument, which is a string + Inputs: function application with one argument, which is a string, + or three arguments: string, integer offset and count Outputs: a new string expression @@ -430,20 +578,20 @@ Function: string_constraint_generatort::add_axioms_for_copy string_exprt string_constraint_generatort::add_axioms_for_copy( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 1)[0]); - const refined_string_typet &ref_type=to_refined_string_type(s1.type()); - string_exprt res=fresh_string(ref_type); - - // We add axioms: - // a1 : |res|=|s1| - // a2 : forall i<|s1|. s1[i]=res[i] - - axioms.push_back(res.axiom_for_has_same_length_as(s1)); - - symbol_exprt idx=fresh_univ_index("QA_index_copy", ref_type.get_index_type()); - string_constraintt a2(idx, s1.length(), equal_exprt(s1[idx], res[idx])); - axioms.push_back(a2); - return res; + const auto &args=f.arguments(); + if(args.size()==1) + { + string_exprt s1=get_string_expr(args[0]); + return s1; + } + else + { + assert(args.size()==3); + string_exprt s1=get_string_expr(args[0]); + exprt offset=args[1]; + exprt count=args[2]; + return add_axioms_for_substring(s1, offset, plus_exprt(offset, count)); + } } /*******************************************************************\ @@ -473,6 +621,28 @@ string_exprt string_constraint_generatort::add_axioms_for_java_char_array( /*******************************************************************\ +Function: string_constraint_generatort::add_axioms_for_char_pointer + + Inputs: an expression of type char + + Outputs: an array expression + + Purpose: for an expression of the form `array[0]` returns `array` + +\*******************************************************************/ + +exprt string_constraint_generatort::add_axioms_for_char_pointer( + const function_application_exprt &fun) +{ + exprt char_pointer=args(fun, 1)[0]; + if(char_pointer.id()==ID_index) + return char_pointer.op0(); + // TODO: we do not know what to do in the other cases + assert(false); +} + +/*******************************************************************\ + Function: string_constraint_generatort::add_axioms_for_length Inputs: function application with one string argument @@ -486,7 +656,7 @@ Function: string_constraint_generatort::add_axioms_for_length exprt string_constraint_generatort::add_axioms_for_length( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 1)[0]); + string_exprt str=get_string_expr(args(f, 1)[0]); return str.length(); } @@ -511,6 +681,7 @@ string_exprt string_constraint_generatort::add_axioms_from_char_array( const exprt &offset, const exprt &count) { + assert(false); // deprecated, we should use add_axioms_for_substring instead const typet &char_type=to_array_type(data.type()).subtype(); const typet &index_type=length.type(); refined_string_typet ref_type(index_type, char_type); @@ -523,7 +694,7 @@ string_exprt string_constraint_generatort::add_axioms_from_char_array( symbol_exprt qvar=fresh_univ_index("QA_string_of_char_array", index_type); exprt char_in_tab=data; assert(char_in_tab.id()==ID_index); - char_in_tab.op1()=plus_exprt(qvar, offset); + char_in_tab.op1()=plus_exprt_with_overflow_check(qvar, offset); string_constraintt a1(qvar, count, equal_exprt(str[qvar], char_in_tab)); axioms.push_back(a1); @@ -549,6 +720,7 @@ Function: string_constraint_generatort::add_axioms_from_char_array string_exprt string_constraint_generatort::add_axioms_from_char_array( const function_application_exprt &f) { + assert(false); // deprecated, we should use add_axioms_for_substring instead exprt offset; exprt count; if(f.arguments().size()==4) @@ -638,7 +810,7 @@ Function: string_constraint_generatort::add_axioms_for_char_at exprt string_constraint_generatort::add_axioms_for_char_at( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 2)[0]); + string_exprt str=get_string_expr(args(f, 2)[0]); const refined_string_typet &ref_type=to_refined_string_type(str.type()); symbol_exprt char_sym=fresh_symbol("char", ref_type.get_char_type()); axioms.push_back(equal_exprt(char_sym, str[args(f, 2)[1]])); @@ -660,26 +832,6 @@ Function: string_constraint_generatort::add_axioms_for_to_char_array exprt string_constraint_generatort::add_axioms_for_to_char_array( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 1)[0]); + string_exprt str=get_string_expr(args(f, 1)[0]); return str.content(); } - -/*******************************************************************\ - -Function: string_constraint_generatort::set_string_symbol_equal_to_expr - - Inputs: a symbol and a string - - Purpose: add a correspondence to make sure the symbol points to the - same string as the second argument - -\*******************************************************************/ - -void string_constraint_generatort::set_string_symbol_equal_to_expr( - const symbol_exprt &sym, const exprt &str) -{ - if(str.id()==ID_symbol) - assign_to_symbol(sym, find_or_add_string_of_symbol(to_symbol_expr(str))); - else - assign_to_symbol(sym, add_axioms_for_string_expr(str)); -} diff --git a/src/solvers/refinement/string_constraint_generator_testing.cpp b/src/solvers/refinement/string_constraint_generator_testing.cpp index 8b1c7bca9d4..2a08b021070 100644 --- a/src/solvers/refinement/string_constraint_generator_testing.cpp +++ b/src/solvers/refinement/string_constraint_generator_testing.cpp @@ -31,15 +31,15 @@ exprt string_constraint_generatort::add_axioms_for_is_prefix( // We add axioms: // a1 : isprefix => |str| >= |prefix|+offset - // a2 : forall 0<=qvar - // s0[witness+offset]=s2[witness] - // a3 : !isprefix => |str| < |prefix|+offset - // || (|str| >= |prefix|+offset &&0<=witness<|prefix| - // &&str[witness+ofsset]!=prefix[witness]) + // a2 : forall 0<=qvar<|prefix|. isprefix => s0[witness+offset]=s2[witness] + // a3 : !isprefix => + // |str|<|prefix|+offset || + // (0<=witness<|prefix| && str[witness+offset]!=prefix[witness]) implies_exprt a1( isprefix, - str.axiom_for_is_longer_than(plus_exprt(prefix.length(), offset))); + str.axiom_for_is_longer_than(plus_exprt_with_overflow_check( + prefix.length(), offset))); axioms.push_back(a1); symbol_exprt qvar=fresh_univ_index("QA_isprefix", index_type); @@ -47,7 +47,8 @@ exprt string_constraint_generatort::add_axioms_for_is_prefix( qvar, prefix.length(), isprefix, - equal_exprt(str[plus_exprt(qvar, offset)], prefix[qvar])); + equal_exprt(str[plus_exprt_with_overflow_check(qvar, offset)], + prefix[qvar])); axioms.push_back(a2); symbol_exprt witness=fresh_exist_index("witness_not_isprefix", index_type); @@ -55,14 +56,13 @@ exprt string_constraint_generatort::add_axioms_for_is_prefix( axiom_for_is_positive_index(witness), and_exprt( prefix.axiom_for_is_strictly_longer_than(witness), - notequal_exprt(str[plus_exprt(witness, offset)], prefix[witness]))); + notequal_exprt(str[plus_exprt_with_overflow_check(witness, offset)], + prefix[witness]))); or_exprt s0_notpref_s1( not_exprt( - str.axiom_for_is_longer_than(plus_exprt(prefix.length(), offset))), - and_exprt( - witness_diff, str.axiom_for_is_longer_than( - plus_exprt(prefix.length(), offset)))); + plus_exprt_with_overflow_check(prefix.length(), offset))), + witness_diff); implies_exprt a3(not_exprt(isprefix), s0_notpref_s1); axioms.push_back(a3); @@ -88,8 +88,8 @@ exprt string_constraint_generatort::add_axioms_for_is_prefix( { const function_application_exprt::argumentst &args=f.arguments(); assert(f.type()==bool_typet() || f.type().id()==ID_c_bool); - string_exprt s0=add_axioms_for_string_expr(args[swap_arguments?1:0]); - string_exprt s1=add_axioms_for_string_expr(args[swap_arguments?0:1]); + string_exprt s0=get_string_expr(args[swap_arguments?1:0]); + string_exprt s1=get_string_expr(args[swap_arguments?0:1]); exprt offset; if(args.size()==2) offset=from_integer(0, s0.length().type()); @@ -121,7 +121,7 @@ exprt string_constraint_generatort::add_axioms_for_is_empty( // a2 : s0 => is_empty symbol_exprt is_empty=fresh_boolean("is_empty"); - string_exprt s0=add_axioms_for_string_expr(args(f, 1)[0]); + string_exprt s0=get_string_expr(args(f, 1)[0]); axioms.push_back(implies_exprt(is_empty, s0.axiom_for_has_length(0))); axioms.push_back(implies_exprt(s0.axiom_for_has_length(0), is_empty)); return typecast_exprt(is_empty, f.type()); @@ -150,8 +150,8 @@ exprt string_constraint_generatort::add_axioms_for_is_suffix( symbol_exprt issuffix=fresh_boolean("issuffix"); typecast_exprt tc_issuffix(issuffix, f.type()); - string_exprt s0=add_axioms_for_string_expr(args[swap_arguments?1:0]); - string_exprt s1=add_axioms_for_string_expr(args[swap_arguments?0:1]); + string_exprt s0=get_string_expr(args[swap_arguments?1:0]); + string_exprt s1=get_string_expr(args[swap_arguments?0:1]); const typet &index_type=s0.length().type(); // We add axioms: @@ -159,7 +159,7 @@ exprt string_constraint_generatort::add_axioms_for_is_suffix( // a2 : forall witness s1[witness]=s0[witness + s0.length-s1.length] // a3 : !issuffix => - // s1.length > s0.length + // (s1.length > s0.length && witness=-1) // || (s1.length > witness>=0 // &&s1[witness]!=s0[witness + s0.length-s1.length] @@ -177,7 +177,8 @@ exprt string_constraint_generatort::add_axioms_for_is_suffix( exprt shifted=plus_exprt( witness, minus_exprt(s1.length(), s0.length())); or_exprt constr3( - s0.axiom_for_is_strictly_longer_than(s1), + and_exprt(s0.axiom_for_is_strictly_longer_than(s1), + equal_exprt(witness, from_integer(-1, index_type))), and_exprt( notequal_exprt(s0[witness], s1[shifted]), and_exprt( @@ -207,9 +208,10 @@ exprt string_constraint_generatort::add_axioms_for_contains( assert(f.type()==bool_typet() || f.type().id()==ID_c_bool); symbol_exprt contains=fresh_boolean("contains"); typecast_exprt tc_contains(contains, f.type()); - string_exprt s0=add_axioms_for_string_expr(args(f, 2)[0]); - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[1]); - const typet &index_type=s0.type(); + string_exprt s0=get_string_expr(args(f, 2)[0]); + string_exprt s1=get_string_expr(args(f, 2)[1]); + const refined_string_typet ref_type=to_refined_string_type(s0.type()); + const typet &index_type=ref_type.get_index_type(); // We add axioms: // a1 : contains => s0.length >= s1.length diff --git a/src/solvers/refinement/string_constraint_generator_transformation.cpp b/src/solvers/refinement/string_constraint_generator_transformation.cpp index 83735e0d5b5..f27fe5d4317 100644 --- a/src/solvers/refinement/string_constraint_generator_transformation.cpp +++ b/src/solvers/refinement/string_constraint_generator_transformation.cpp @@ -29,7 +29,7 @@ Function: string_constraint_generatort::add_axioms_for_set_length string_exprt string_constraint_generatort::add_axioms_for_set_length( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); + string_exprt s1=get_string_expr(args(f, 2)[0]); exprt k=args(f, 2)[1]; const refined_string_typet &ref_type=to_refined_string_type(s1.type()); string_exprt res=fresh_string(ref_type); @@ -76,7 +76,7 @@ string_exprt string_constraint_generatort::add_axioms_for_substring( { const function_application_exprt::argumentst &args=f.arguments(); assert(args.size()>=2); - string_exprt str=add_axioms_for_string_expr(args[0]); + string_exprt str=get_string_expr(args[0]); exprt i(args[1]); exprt j; if(args.size()==3) @@ -110,7 +110,6 @@ string_exprt string_constraint_generatort::add_axioms_for_substring( { const refined_string_typet &ref_type=to_refined_string_type(str.type()); const typet &index_type=ref_type.get_index_type(); - symbol_exprt idx=fresh_exist_index("index_substring", index_type); assert(start.type()==index_type); assert(end.type()==index_type); string_exprt res=fresh_string(ref_type); @@ -133,8 +132,11 @@ string_exprt string_constraint_generatort::add_axioms_for_substring( // Warning: check what to do if the string is not long enough axioms.push_back(str.axiom_for_is_longer_than(end)); - string_constraintt a4( - idx, res.length(), equal_exprt(res[idx], str[plus_exprt(start, idx)])); + symbol_exprt idx=fresh_univ_index("QA_index_substring", index_type); + string_constraintt a4(idx, + res.length(), + equal_exprt(res[idx], + str[plus_exprt_with_overflow_check(start, idx)])); axioms.push_back(a4); return res; } @@ -154,7 +156,7 @@ Function: string_constraint_generatort::add_axioms_for_trim string_exprt string_constraint_generatort::add_axioms_for_trim( const function_application_exprt &expr) { - string_exprt str=add_axioms_for_string_expr(args(expr, 1)[0]); + string_exprt str=get_string_expr(args(expr, 1)[0]); const refined_string_typet &ref_type=to_refined_string_type(str.type()); const typet &index_type=ref_type.get_index_type(); string_exprt res=fresh_string(ref_type); @@ -173,7 +175,8 @@ string_exprt string_constraint_generatort::add_axioms_for_trim( // a8 : forall n<|s1|, s[idx+n]=s1[n] // a9 : (s[m]>' ' &&s[m+|s1|-1]>' ') || m=|s| - exprt a1=str.axiom_for_is_longer_than(plus_exprt(idx, res.length())); + exprt a1=str.axiom_for_is_longer_than( + plus_exprt_with_overflow_check(idx, res.length())); axioms.push_back(a1); binary_relation_exprt a2(idx, ID_ge, from_integer(0, index_type)); @@ -195,7 +198,8 @@ string_exprt string_constraint_generatort::add_axioms_for_trim( axioms.push_back(a6); symbol_exprt n2=fresh_univ_index("QA_index_trim2", index_type); - minus_exprt bound(str.length(), plus_exprt(idx, res.length())); + minus_exprt bound(str.length(), plus_exprt_with_overflow_check(idx, + res.length())); binary_relation_exprt eqn2( str[plus_exprt(idx, plus_exprt(res.length(), n2))], ID_le, @@ -210,7 +214,8 @@ string_exprt string_constraint_generatort::add_axioms_for_trim( axioms.push_back(a8); minus_exprt index_before( - plus_exprt(idx, res.length()), from_integer(1, index_type)); + plus_exprt_with_overflow_check(idx, res.length()), + from_integer(1, index_type)); binary_relation_exprt no_space_before(str[index_before], ID_gt, space_char); or_exprt a9( equal_exprt(idx, str.length()), @@ -236,7 +241,7 @@ Function: string_constraint_generatort::add_axioms_for_to_lower_case string_exprt string_constraint_generatort::add_axioms_for_to_lower_case( const function_application_exprt &expr) { - string_exprt str=add_axioms_for_string_expr(args(expr, 1)[0]); + string_exprt str=get_string_expr(args(expr, 1)[0]); const refined_string_typet &ref_type=to_refined_string_type(str.type()); const typet &char_type=ref_type.get_char_type(); const typet &index_type=ref_type.get_index_type(); @@ -289,7 +294,7 @@ Function: string_constraint_generatort::add_axioms_for_to_upper_case string_exprt string_constraint_generatort::add_axioms_for_to_upper_case( const function_application_exprt &expr) { - string_exprt str=add_axioms_for_string_expr(args(expr, 1)[0]); + string_exprt str=get_string_expr(args(expr, 1)[0]); const refined_string_typet &ref_type=to_refined_string_type(str.type()); const typet &char_type=ref_type.get_char_type(); const typet &index_type=ref_type.get_index_type(); @@ -345,7 +350,7 @@ Function: string_constraint_generatort::add_axioms_for_char_set string_exprt string_constraint_generatort::add_axioms_for_char_set( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 3)[0]); + string_exprt str=get_string_expr(args(f, 3)[0]); const refined_string_typet &ref_type=to_refined_string_type(str.type()); string_exprt res=fresh_string(ref_type); with_exprt sarrnew(str.content(), args(f, 3)[1], args(f, 3)[2]); @@ -378,7 +383,7 @@ Function: string_constraint_generatort::add_axioms_for_replace string_exprt string_constraint_generatort::add_axioms_for_replace( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 3)[0]); + string_exprt str=get_string_expr(args(f, 3)[0]); const refined_string_typet &ref_type=to_refined_string_type(str.type()); const exprt &old_char=args(f, 3)[1]; const exprt &new_char=args(f, 3)[2]; @@ -421,10 +426,12 @@ Function: string_constraint_generatort::add_axioms_for_delete_char_at string_exprt string_constraint_generatort::add_axioms_for_delete_char_at( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 2)[0]); + string_exprt str=get_string_expr(args(f, 2)[0]); exprt index_one=from_integer(1, str.length().type()); return add_axioms_for_delete( - str, args(f, 2)[1], plus_exprt(args(f, 2)[1], index_one)); + str, + args(f, 2)[1], + plus_exprt_with_overflow_check(args(f, 2)[1], index_one)); } /*******************************************************************\ @@ -468,6 +475,6 @@ Function: string_constraint_generatort::add_axioms_for_delete string_exprt string_constraint_generatort::add_axioms_for_delete( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 3)[0]); + string_exprt str=get_string_expr(args(f, 3)[0]); return add_axioms_for_delete(str, args(f, 3)[1], args(f, 3)[2]); } diff --git a/src/solvers/refinement/string_constraint_generator_valueof.cpp b/src/solvers/refinement/string_constraint_generator_valueof.cpp index d1030e5e085..10fe490259a 100644 --- a/src/solvers/refinement/string_constraint_generator_valueof.cpp +++ b/src/solvers/refinement/string_constraint_generator_valueof.cpp @@ -63,7 +63,8 @@ Function: string_constraint_generatort::add_axioms_from_float string_exprt string_constraint_generatort::add_axioms_from_float( const function_application_exprt &f) { - return add_axioms_from_float(args(f, 1)[0], false); + const refined_string_typet &ref_type=to_refined_string_type(f.type()); + return add_axioms_from_float(args(f, 1)[0], ref_type, false); } /*******************************************************************\ @@ -81,7 +82,8 @@ Function: string_constraint_generatort::add_axioms_from_double string_exprt string_constraint_generatort::add_axioms_from_double( const function_application_exprt &f) { - return add_axioms_from_float(args(f, 1)[0], true); + const refined_string_typet &ref_type=to_refined_string_type(f.type()); + return add_axioms_from_float(args(f, 1)[0], ref_type, true); } /*******************************************************************\ @@ -99,13 +101,12 @@ Function: string_constraint_generatort::add_axioms_from_float \*******************************************************************/ string_exprt string_constraint_generatort::add_axioms_from_float( - const exprt &f, bool double_precision) + const exprt &f, const refined_string_typet &ref_type, bool double_precision) { - const refined_string_typet &ref_type=to_refined_string_type(f.type()); + string_exprt res=fresh_string(ref_type); const typet &index_type=ref_type.get_index_type(); const typet &char_type=ref_type.get_char_type(); - string_exprt res=fresh_string(ref_type); - const exprt &index24=from_integer(24, ref_type.get_index_type()); + const exprt &index24=from_integer(24, index_type); axioms.push_back(res.axiom_for_is_shorter_than(index24)); string_exprt magnitude=fresh_string(ref_type); @@ -323,13 +324,22 @@ string_exprt string_constraint_generatort::add_axioms_from_int( axioms.push_back(a1); exprt chr=res[0]; - exprt starts_with_minus=equal_exprt(chr, minus_char); - exprt starts_with_digit=and_exprt( + equal_exprt starts_with_minus(chr, minus_char); + and_exprt starts_with_digit( binary_relation_exprt(chr, ID_ge, zero_char), binary_relation_exprt(chr, ID_le, nine_char)); or_exprt a2(starts_with_digit, starts_with_minus); axioms.push_back(a2); + // These are constraints to detect number that requiere the maximum number + // of digits + exprt smallest_with_max_digits= + from_integer(smallest_by_digit(max_size-1), type); + binary_relation_exprt big_negative( + i, ID_le, unary_minus_exprt(smallest_with_max_digits)); + binary_relation_exprt big_positive(i, ID_ge, smallest_with_max_digits); + or_exprt requieres_max_digits(big_negative, big_positive); + for(size_t size=1; size<=max_size; size++) { // For each possible size, we add axioms: @@ -387,13 +397,18 @@ string_exprt string_constraint_generatort::add_axioms_from_int( axioms.push_back(a6); } - // we have to be careful when exceeding the maximal size of integers + // when the size is close to the maximum, either the number is very big + // or it is negative + if(size==max_size-1) + { + implies_exprt a7(premise, or_exprt(requieres_max_digits, + starts_with_minus)); + axioms.push_back(a7); + } + // when we reach the maximal size the number is very big in the negative if(size==max_size) { - exprt smallest_with_10_digits=from_integer( - smallest_by_digit(max_size), type); - binary_relation_exprt big(i, ID_ge, smallest_with_10_digits); - implies_exprt a7(premise, big); + implies_exprt a7(premise, and_exprt(starts_with_minus, big_negative)); axioms.push_back(a7); } } @@ -597,6 +612,60 @@ string_exprt string_constraint_generatort::add_axioms_for_value_of( /*******************************************************************\ +Function: string_constraint_generatort::add_axioms_for_correct_number_format + + Inputs: function application with one string expression + + Outputs: an boolean expression + + Purpose: add axioms making the return value true if the given string is + a correct number + +\*******************************************************************/ + +exprt string_constraint_generatort::add_axioms_for_correct_number_format( + const string_exprt &str, std::size_t max_size) +{ + symbol_exprt correct=fresh_boolean("correct_number_format"); + const refined_string_typet &ref_type=to_refined_string_type(str.type()); + const typet &char_type=ref_type.get_char_type(); + const typet &index_type=ref_type.get_index_type(); + exprt zero_char=constant_char('0', char_type); + exprt nine_char=constant_char('9', char_type); + exprt minus_char=constant_char('-', char_type); + exprt plus_char=constant_char('+', char_type); + + exprt chr=str[0]; + equal_exprt starts_with_minus(chr, minus_char); + equal_exprt starts_with_plus(chr, plus_char); + and_exprt starts_with_digit( + binary_relation_exprt(chr, ID_ge, zero_char), + binary_relation_exprt(chr, ID_le, nine_char)); + + or_exprt correct_first( + or_exprt(starts_with_minus, starts_with_plus), starts_with_digit); + exprt has_first=str.axiom_for_is_longer_than(from_integer(1, index_type)); + implies_exprt a1(correct, and_exprt(has_first, correct_first)); + axioms.push_back(a1); + + exprt not_too_long=str.axiom_for_is_shorter_than(max_size); + axioms.push_back(not_too_long); + + symbol_exprt qvar=fresh_univ_index("number_format", index_type); + + and_exprt is_digit( + binary_relation_exprt(str[qvar], ID_ge, zero_char), + binary_relation_exprt(str[qvar], ID_le, nine_char)); + + string_constraintt a2( + qvar, from_integer(1, index_type), str.length(), correct, is_digit); + + axioms.push_back(a2); + return correct; +} + +/*******************************************************************\ + Function: string_constraint_generatort::add_axioms_for_parse_int Inputs: function application with one string expression @@ -610,7 +679,7 @@ Function: string_constraint_generatort::add_axioms_for_parse_int exprt string_constraint_generatort::add_axioms_for_parse_int( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 1)[0]); + string_exprt str=get_string_expr(args(f, 1)[0]); const typet &type=f.type(); symbol_exprt i=fresh_symbol("parsed_int", type); const refined_string_typet &ref_type=to_refined_string_type(str.type()); @@ -626,6 +695,10 @@ exprt string_constraint_generatort::add_axioms_for_parse_int( exprt starts_with_plus=equal_exprt(chr, plus_char); exprt starts_with_digit=binary_relation_exprt(chr, ID_ge, zero_char); + // TODO: we should throw an exception when this does not hold: + exprt correct=add_axioms_for_correct_number_format(str); + axioms.push_back(correct); + for(unsigned size=1; size<=10; size++) { exprt sum=from_integer(0, type); diff --git a/src/solvers/refinement/string_refinement.cpp b/src/solvers/refinement/string_refinement.cpp index db9a2c460cc..1391ffd2315 100644 --- a/src/solvers/refinement/string_refinement.cpp +++ b/src/solvers/refinement/string_refinement.cpp @@ -11,17 +11,38 @@ Author: Alberto Griggio, alberto.griggio@gmail.com \*******************************************************************/ #include +#include #include #include #include +#include +#include #include #include #include +#include + +/*******************************************************************\ + +Constructor: string_refinementt + + Inputs: a namespace, a decision procedure, a bound on the number + of refinements and a boolean flag `concretize_result` + + Purpose: refinement_bound is a bound on the number of refinement allowed. + if `concretize_result` is set to true, at the end of the decision + procedure, the solver try to find a concrete value for each + character + +\*******************************************************************/ string_refinementt::string_refinementt( - const namespacet &_ns, propt &_prop, unsigned refinement_bound): + const namespacet &_ns, + propt &_prop, + unsigned refinement_bound): supert(_ns, _prop), use_counter_example(false), + do_concretizing(false), initial_loop_bound(refinement_bound) { } @@ -52,15 +73,27 @@ Function: string_refinementt::display_index_set void string_refinementt::display_index_set() { + std::size_t count=0; + std::size_t count_current=0; for(const auto &i : index_set) { const exprt &s=i.first; - debug() << "IS(" << from_expr(s) << ")=={"; + debug() << "IS(" << from_expr(s) << ")=={" << eom; for(auto j : i.second) - debug() << from_expr(j) << "; "; + { + if(current_index_set[i.first].find(j)!=current_index_set[i.first].end()) + { + count_current++; + debug() << "**"; + } + debug() << " " << from_expr(j) << ";" << eom; + count++; + } debug() << "}" << eom; } + debug() << count << " elements in index set (" << count_current + << " newly added)" << eom; } /*******************************************************************\ @@ -100,152 +133,320 @@ void string_refinementt::add_instantiations() /*******************************************************************\ -Function: string_refinementt::convert_rest - - Inputs: an expression +Function: string_refinementt::add_symbol_to_symbol_map() - Outputs: a literal + Inputs: a symbol and the expression to map it to - Purpose: if the expression is a function application, we convert it - using our own convert_function_application method + Purpose: keeps a map of symbols to expressions, such as none of the + mapped values exist as a key \*******************************************************************/ -literalt string_refinementt::convert_rest(const exprt &expr) +void string_refinementt::add_symbol_to_symbol_map +(const exprt &lhs, const exprt &rhs) { - if(expr.id()==ID_function_application) + assert(lhs.id()==ID_symbol); + + // We insert the mapped value of the rhs, if it exists. + auto it=symbol_resolve.find(rhs); + const exprt &new_rhs=it!=symbol_resolve.end()?it->second:rhs; + + symbol_resolve[lhs]=new_rhs; + reverse_symbol_resolve[new_rhs].push_back(lhs); + + std::list symbols_to_update_with_new_rhs(reverse_symbol_resolve[rhs]); + for(exprt item : symbols_to_update_with_new_rhs) { - // can occur in __CPROVER_assume - bvt bv=convert_function_application(to_function_application_expr(expr)); - assert(bv.size()==1); - return bv[0]; + symbol_resolve[item]=new_rhs; + reverse_symbol_resolve[new_rhs].push_back(item); } - else +} + +/*******************************************************************\ + +Function: string_refinementt::set_char_array_equality() + + Inputs: the rhs and lhs of an equality over character arrays + + Purpose: add axioms if the rhs is a character array + +\*******************************************************************/ + +void string_refinementt::set_char_array_equality( + const exprt &lhs, const exprt &rhs) +{ + assert(lhs.id()==ID_symbol); + + if(rhs.id()==ID_array && rhs.type().id()==ID_array) { - return supert::convert_rest(expr); + const typet &index_type=to_array_type(rhs.type()).size().type(); + for(size_t i=0, ilim=rhs.operands().size(); i!=ilim; ++i) + { + // Introduce axioms to map symbolic rhs to its char array. + index_exprt arraycell(rhs, from_integer(i, index_type)); + equal_exprt arrayeq(arraycell, rhs.operands()[i]); + add_lemma(arrayeq, false); +#if 0 + generator.axioms.push_back(arrayeq); +#endif + } } + // At least for Java (as it is currently pre-processed), we need not consider + // other cases, because all character arrays find themselves on the rhs of an + // equality. Note that this might not be the case for other languages. } /*******************************************************************\ -Function: string_refinementt::convert_symbol +Function: string_refinementt::substitute_function_applications() - Inputs: an expression + Inputs: an expression containing function applications - Outputs: a bitvector + Outputs: an epression containing no function application - Purpose: if the expression as string type, look up for the string in the - list of string symbols that we maintain, and convert it; - otherwise use the method of the parent class + Purpose: remove functions applications and create the necessary + axioms \*******************************************************************/ -bvt string_refinementt::convert_symbol(const exprt &expr) +exprt string_refinementt::substitute_function_applications(exprt expr) { - const typet &type=expr.type(); - const irep_idt &identifier=expr.get(ID_identifier); - assert(!identifier.empty()); + for(size_t i=0; iMAX_CONCRETE_STRING_SIZE? + MAX_CONCRETE_STRING_SIZE:concretize_limit; + exprt content_expr=str.content(); + replace_expr(current_model, content_expr); + for(size_t i=0; i &pair : non_string_axioms) + { + replace_expr(symbol_resolve, pair.first); + debug() << "super::set_to " << from_expr(pair.first) << eom; + supert::set_to(pair.first, pair.second); + } + + for(exprt &axiom : generator.axioms) + { + replace_expr(symbol_resolve, axiom); if(axiom.id()==ID_string_constraint) { string_constraintt c=to_string_constraint(axiom); @@ -282,6 +494,7 @@ decision_proceduret::resultt string_refinementt::dec_solve() { add_lemma(axiom); } + } initial_index_set(universal_axioms); update_index_set(cur); @@ -302,6 +515,7 @@ decision_proceduret::resultt string_refinementt::dec_solve() else { debug() << "check_SAT: the model is correct" << eom; + concretize_lengths(); return D_SATISFIABLE; } @@ -318,7 +532,13 @@ decision_proceduret::resultt string_refinementt::dec_solve() if(current_index_set.empty()) { debug() << "current index set is empty" << eom; - return D_SATISFIABLE; + if(do_concretizing) + { + concretize_results(); + do_concretizing=false; + } + else + return D_SATISFIABLE; } display_index_set(); @@ -367,131 +587,337 @@ bvt string_refinementt::convert_bool_bv(const exprt &boole, const exprt &orig) Function: string_refinementt::add_lemma - Inputs: a lemma + Inputs: a lemma and Boolean value stating whether the lemma should + be added to the index set. Purpose: add the given lemma to the solver \*******************************************************************/ -void string_refinementt::add_lemma(const exprt &lemma, bool add_to_index_set) +void string_refinementt::add_lemma( + const exprt &lemma, bool _simplify, bool add_to_index_set) { if(!seen_instances.insert(lemma).second) return; - if(lemma.is_true()) + if(add_to_index_set) + cur.push_back(lemma); + + exprt simple_lemma=lemma; + if(_simplify) + simplify(simple_lemma, ns); + + if(simple_lemma.is_true()) { +#if 0 debug() << "string_refinementt::add_lemma : tautology" << eom; +#endif return; } - debug() << "adding lemma " << from_expr(lemma) << eom; + debug() << "adding lemma " << from_expr(simple_lemma) << eom; - prop.l_set_to_true(convert(lemma)); - if(add_to_index_set) - cur.push_back(lemma); + prop.l_set_to_true(convert(simple_lemma)); } /*******************************************************************\ -Function: string_refinementt::string_of_array +Function: string_refinementt::get_array - Inputs: a constant array expression and a integer expression + Inputs: an expression representing an array and an expression + representing an integer - Outputs: a string + Outputs: an array expression or an array_of_exprt - Purpose: convert the content of a string to a more readable representation. - This should only be used for debbuging. + Purpose: get a model of an array and put it in a certain form. + If the size cannot be obtained or if it is too big, return an + empty array. \*******************************************************************/ -std::string string_refinementt::string_of_array( - const exprt &arr, const exprt &size) const +exprt string_refinementt::get_array(const exprt &arr, const exprt &size) const { - if(size.id()!=ID_constant) - return "string of unknown size"; + exprt arr_val=get_array(arr); + exprt size_val=supert::get(size); + size_val=simplify_expr(size_val, ns); + typet char_type=arr.type().subtype(); + typet index_type=size.type(); + array_typet empty_ret_type(char_type, from_integer(0, index_type)); + array_of_exprt empty_ret(from_integer(0, char_type), empty_ret_type); + + if(size_val.id()!=ID_constant) + { +#if 0 + debug() << "(sr::get_array) string of unknown size: " + << from_expr(size_val) << eom; +#endif + return empty_ret; + } + unsigned n; - if(to_unsigned_integer(to_constant_expr(size), n)) - n=0; + if(to_unsigned_integer(to_constant_expr(size_val), n)) + { +#if 0 + debug() << "(sr::get_array) size is not valid" << eom; +#endif + return empty_ret; + } + + array_typet ret_type(char_type, from_integer(n, index_type)); + array_exprt ret(ret_type); if(n>MAX_CONCRETE_STRING_SIZE) - return "very long string"; + { +#if 0 + debug() << "(sr::get_array) long string (size=" << n << ")" << eom; +#endif + return empty_ret; + } + if(n==0) - return "\"\""; + { +#if 0 + debug() << "(sr::get_array) empty string" << eom; +#endif + return empty_ret; + } - std::ostringstream buf; - buf << "\""; - exprt val=get(arr); + std::vector concrete_array(n); - if(val.id()=="array-list") + if(arr_val.id()=="array-list") { - for(size_t i=0; i(c); + exprt value=arr_val.operands()[i*2+1]; + to_unsigned_integer(to_constant_expr(value), concrete_array[idx]); } } } } + else if(arr_val.id()==ID_array) + { + for(size_t i=0; i=32) + result << (unsigned char) c; + else + { + result << "\\u" << std::hex << std::setw(4) << std::setfill('0') + << (unsigned int) c; + } + } + + return result.str(); +} + +/*******************************************************************\ - for(size_t i=0; i &m, bool negated) const + std::map &m, const typet &type, bool negated) const { exprt sum=nil_exprt(); mp_integer constants=0; typet index_type; if(m.empty()) - return nil_exprt(); + return from_integer(0, type); else index_type=m.begin()->first.type(); @@ -723,12 +1122,20 @@ exprt string_refinementt::sum_over_map( default: if(second>1) { - for(int i=0; isecond; i--) + if(sum.is_nil()) + sum=unary_minus_exprt(t); + else + sum=minus_exprt(sum, t); + for(int i=-1; i>second; i--) sum=minus_exprt(sum, t); } } @@ -755,7 +1162,7 @@ Function: string_refinementt::simplify_sum exprt string_refinementt::simplify_sum(const exprt &f) const { std::map map=map_representation_of_sum(f); - return sum_over_map(map); + return sum_over_map(map, f.type()); } /*******************************************************************\ @@ -800,7 +1207,7 @@ exprt string_refinementt::compute_inverse_function( } elems.erase(it); - return sum_over_map(elems, neg); + return sum_over_map(elems, f.type(), neg); } @@ -830,7 +1237,7 @@ Function: find_qvar Outputs: a Boolean - Purpose: looks for the symbol and return true if it is found + Purpose: look for the symbol and return true if it is found \*******************************************************************/ @@ -885,6 +1292,26 @@ Function: string_refinementt::initial_index_set and the upper bound minus one \*******************************************************************/ +void string_refinementt::add_to_index_set(const exprt &s, exprt i) +{ + simplify(i, ns); + if(i.id()==ID_constant) + { + mp_integer mpi; + to_integer(i, mpi); + if(mpi<0) + { + debug() << "add_to_index_set : ignoring negative number " << mpi << eom; + return; + } + } + if(index_set[s].insert(i).second) + { + debug() << "adding to index set of " << from_expr(s) + << ": " << from_expr(i) << eom; + current_index_set[s].insert(i); + } +} void string_refinementt::initial_index_set(const string_constraintt &axiom) { @@ -906,8 +1333,7 @@ void string_refinementt::initial_index_set(const string_constraintt &axiom) // if cur is of the form s[i] and no quantified variable appears in i if(!has_quant_var) { - current_index_set[s].insert(i); - index_set[s].insert(i); + add_to_index_set(s, i); } else { @@ -917,8 +1343,7 @@ void string_refinementt::initial_index_set(const string_constraintt &axiom) axiom.upper_bound(), from_integer(1, axiom.upper_bound().type())); replace_expr(qvar, kminus1, e); - current_index_set[s].insert(e); - index_set[s].insert(e); + add_to_index_set(s, e); } } else @@ -952,12 +1377,7 @@ void string_refinementt::update_index_set(const exprt &formula) const exprt &i=cur.op1(); assert(s.type().id()==ID_array); exprt simplified=simplify_sum(i); - if(index_set[s].insert(simplified).second) - { - debug() << "adding to index set of " << from_expr(s) - << ": " << from_expr(simplified) << eom; - current_index_set[s].insert(simplified); - } + add_to_index_set(s, simplified); } else { @@ -1014,19 +1434,18 @@ exprt find_index(const exprt &expr, const exprt &str) catch (exprt i) { return i; } } - /*******************************************************************\ Function: string_refinementt::instantiate - Inputs: an universaly quantified formula `axiom`, an array of char + Inputs: a universally quantified formula `axiom`, an array of char variable `str`, and an index expression `val`. - Outputs: substitute `qvar` the universaly quantified variable of `axiom`, by + Outputs: substitute `qvar` the universally quantified variable of `axiom`, by an index `val`, in `axiom`, so that the index used for `str` equals `val`. For instance, if `axiom` corresponds to - $\forall q. s[q+x]='a' && t[q]='b'$, `instantiate(axom,s,v)` would return - an expression for $s[v]='a' && t[v-x]='b'$. + $\forall q. s[q+x]='a' && t[q]='b'$, `instantiate(axom,s,v)` + would return an expression for $s[v]='a' && t[v-x]='b'$. \*******************************************************************/ @@ -1051,6 +1470,17 @@ exprt string_refinementt::instantiate( return implies_exprt(bounds, instance); } +/*******************************************************************\ + +Function: string_refinementt::instantiate_not_contains + + Inputs: a quantified formula representing `not_contains`, and a + list to which to add the created lemmas to + + Purpose: instantiate a quantified formula representing `not_contains` + by substituting the quantifiers and generating axioms + +\*******************************************************************/ void string_refinementt::instantiate_not_contains( const string_not_contains_constraintt &axiom, std::list &new_lemmas) @@ -1102,3 +1532,76 @@ void string_refinementt::instantiate_not_contains( new_lemmas.push_back(witness_bounds); } } + +/*******************************************************************\ + +Function: string_refinementt::substitute_array_lists() + + Inputs: an expression containing array-list expressions + + Outputs: an epression containing no array-list + + Purpose: replace array-lists by 'with' expressions + +\*******************************************************************/ + +exprt string_refinementt::substitute_array_lists(exprt expr) const +{ + for(size_t i=0; i=2); + typet &char_type=expr.operands()[1].type(); + array_typet arr_type(char_type, infinity_exprt(char_type)); + array_of_exprt new_arr(from_integer(0, char_type), + arr_type); + + with_exprt ret_expr(new_arr, + expr.operands()[0], + expr.operands()[1]); + + for(size_t i=2; isecond); + } + + ecopy=supert::get(ecopy); + + return substitute_array_lists(ecopy); +} diff --git a/src/solvers/refinement/string_refinement.h b/src/solvers/refinement/string_refinement.h index be0cd332bc3..252146f4620 100644 --- a/src/solvers/refinement/string_refinement.h +++ b/src/solvers/refinement/string_refinement.h @@ -14,6 +14,7 @@ Author: Alberto Griggio, alberto.griggio@gmail.com #define CPROVER_SOLVERS_REFINEMENT_STRING_REFINEMENT_H #include +#include #include #include @@ -27,30 +28,32 @@ Author: Alberto Griggio, alberto.griggio@gmail.com class string_refinementt: public bv_refinementt { public: - // refinement_bound is a bound on the number of refinement allowed string_refinementt( - const namespacet &_ns, propt &_prop, unsigned refinement_bound); + const namespacet &_ns, + propt &_prop, + unsigned refinement_bound); void set_mode(); // Should we use counter examples at each iteration? bool use_counter_example; - virtual std::string decision_procedure_text() const + bool do_concretizing; + + virtual std::string decision_procedure_text() const override { return "string refinement loop with "+prop.solver_text(); } static exprt is_positive(const exprt &x); + exprt get(const exprt &expr) const override; + protected: typedef std::set expr_sett; + typedef std::list exprt_listt; - virtual bvt convert_symbol(const exprt &expr); - virtual bvt convert_function_application( - const function_application_exprt &expr); - - decision_proceduret::resultt dec_solve(); + decision_proceduret::resultt dec_solve() override; bvt convert_bool_bv(const exprt &boole, const exprt &orig); @@ -60,6 +63,9 @@ class string_refinementt: public bv_refinementt unsigned initial_loop_bound; + // Is the current model correct + bool concrete_model; + string_constraint_generatort generator; // Simple constraints that have been given to the solver @@ -76,23 +82,42 @@ class string_refinementt: public bv_refinementt // Warning: this is indexed by array_expressions and not string expressions std::map current_index_set; std::map index_set; + replace_mapt symbol_resolve; + std::map reverse_symbol_resolve; + std::list> non_string_axioms; - void display_index_set(); + // Valuation in the current model of the symbols that have been created + // by the solver + replace_mapt current_model; - void add_lemma(const exprt &lemma, bool add_to_index_set=true); + void add_equivalence(const irep_idt & lhs, const exprt & rhs); - bool boolbv_set_equality_to_true(const equal_exprt &expr); + void display_index_set(); - literalt convert_rest(const exprt &expr); + void add_lemma(const exprt &lemma, + bool simplify=true, + bool add_to_index_set=true); - void add_instantiations(); + exprt substitute_function_applications(exprt expr); + typet substitute_java_string_types(typet type); + exprt substitute_java_strings(exprt expr); + void add_symbol_to_symbol_map(const exprt &lhs, const exprt &rhs); + bool is_char_array(const typet &type) const; + bool add_axioms_for_string_assigns(const exprt &lhs, const exprt &rhs); + void set_to(const exprt &expr, bool value) override; + void add_instantiations(); + void add_negation_of_constraint_to_solver( + const string_constraintt &axiom, supert &solver); + void fill_model(); bool check_axioms(); + void set_char_array_equality(const exprt &lhs, const exprt &rhs); void update_index_set(const exprt &formula); void update_index_set(const std::vector &cur); void initial_index_set(const string_constraintt &axiom); void initial_index_set(const std::vector &string_axioms); + void add_to_index_set(const exprt &s, exprt i); exprt instantiate( const string_constraintt &axiom, const exprt &str, const exprt &val); @@ -101,17 +126,26 @@ class string_refinementt: public bv_refinementt const string_not_contains_constraintt &axiom, std::list &new_lemmas); + exprt substitute_array_lists(exprt) const; + exprt compute_inverse_function( const exprt &qvar, const exprt &val, const exprt &f); std::map map_representation_of_sum(const exprt &f) const; - exprt sum_over_map(std::map &m, bool negated=false) const; + exprt sum_over_map( + std::map &m, const typet &type, bool negated=false) const; exprt simplify_sum(const exprt &f) const; - exprt get_array(const exprt &arr, const exprt &size); + void concretize_results(); + void concretize_lengths(); + // Length of char arrays found during concretization + std::map found_length; + + exprt get_array(const exprt &arr, const exprt &size) const; + exprt get_array(const exprt &arr) const; - std::string string_of_array(const exprt &arr, const exprt &size) const; + std::string string_of_array(const array_exprt &arr); }; #endif From 6958a561df0a601687cdee2230d4df4f8f3a6176 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Wed, 22 Mar 2017 15:05:40 +0000 Subject: [PATCH 137/699] Need to assign length before calls since it can be overwritten by functions with side-effect --- src/goto-programs/string_refine_preprocess.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/goto-programs/string_refine_preprocess.cpp b/src/goto-programs/string_refine_preprocess.cpp index 8403d4bf044..7243f66049a 100644 --- a/src/goto-programs/string_refine_preprocess.cpp +++ b/src/goto-programs/string_refine_preprocess.cpp @@ -361,7 +361,16 @@ exprt string_refine_preprocesst::make_cprover_string_assign( std::list assignments; // 1) cprover_string_length= *(rhs->length) + symbolt sym_length=get_fresh_aux_symbol( + length_type, + "cprover_string_length", + "cprover_string_length", + location, + ID_java, + symbol_table); + symbol_exprt cprover_length=sym_length.symbol_expr(); member_exprt length(deref, "length", length_type); + assignments.emplace_back(cprover_length, length); // 2) cprover_string_array = *(rhs->data) symbol_exprt array_lhs=fresh_array(data_type.subtype(), location); @@ -373,7 +382,7 @@ exprt string_refine_preprocesst::make_cprover_string_assign( // This assignment is useful for finding witnessing strings for counter // examples refined_string_typet ref_type(length_type, java_char_type()); - string_exprt new_rhs(length, array_lhs, ref_type); + string_exprt new_rhs(cprover_length, array_lhs, ref_type); symbol_exprt lhs=fresh_string(new_rhs.type(), location); assignments.emplace_back(lhs, new_rhs); From df36fecdef239ef7ede60f4873d28e199ca30dc9 Mon Sep 17 00:00:00 2001 From: Joel Allred Date: Thu, 23 Mar 2017 15:05:27 +0000 Subject: [PATCH 138/699] const refs and clean up Corrections on PR 675 requested by Peter Schrammel --- src/goto-programs/string_refine_preprocess.cpp | 10 ++++++---- .../refinement/string_constraint_generator_main.cpp | 12 ++++++++++++ src/solvers/refinement/string_refinement.h | 3 --- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/goto-programs/string_refine_preprocess.cpp b/src/goto-programs/string_refine_preprocess.cpp index 7243f66049a..8b491bab0ab 100644 --- a/src/goto-programs/string_refine_preprocess.cpp +++ b/src/goto-programs/string_refine_preprocess.cpp @@ -809,11 +809,13 @@ void string_refine_preprocesst::make_string_function_side_effect( const irep_idt &function_name, const std::string &signature) { + // Cannot use const & here code_function_callt function_call=to_code_function_call(target->code); source_locationt loc=function_call.source_location(); std::list assignments; - exprt lhs=function_call.lhs(); - exprt s=function_call.arguments()[0]; + const exprt &lhs=function_call.lhs(); + assert(!function_call.arguments().empty()); + const exprt &s=function_call.arguments()[0]; code_typet function_type=to_code_type(function_call.type()); function_type.return_type()=s.type(); @@ -901,7 +903,7 @@ void string_refine_preprocesst::make_to_char_array_function( const code_function_callt &function_call=to_code_function_call(target->code); source_locationt location=function_call.source_location(); - assert(function_call.arguments().size()>=1); + assert(!function_call.arguments().empty()); const exprt &string_argument=function_call.arguments()[0]; assert(is_java_string_pointer_type(string_argument.type())); @@ -985,7 +987,7 @@ exprt::operandst string_refine_preprocesst::process_arguments( arg=typecast_exprt(arg, jls_ptr); } arg=make_cprover_string_assign(goto_program, target, arg, location); - typet type=ns.follow(arg.type()); + const typet &type=ns.follow(arg.type()); if(is_java_char_array_pointer_type(type)) { arg=make_cprover_char_array_assign(goto_program, target, arg, location); diff --git a/src/solvers/refinement/string_constraint_generator_main.cpp b/src/solvers/refinement/string_constraint_generator_main.cpp index f8dedaab9a7..e4292da542b 100644 --- a/src/solvers/refinement/string_constraint_generator_main.cpp +++ b/src/solvers/refinement/string_constraint_generator_main.cpp @@ -208,6 +208,18 @@ string_exprt string_constraint_generatort::get_string_expr(const exprt &expr) } } +/*******************************************************************\ + +Function: string_constraint_generatort::convert_java_string_to_string_exprt + + Inputs: a java string + + Outputs: a string expression + + Purpose: create a new string_exprt as a conversion of a java string + +\*******************************************************************/ + string_exprt string_constraint_generatort::convert_java_string_to_string_exprt( const exprt &jls) { diff --git a/src/solvers/refinement/string_refinement.h b/src/solvers/refinement/string_refinement.h index 252146f4620..0a62a6abe7d 100644 --- a/src/solvers/refinement/string_refinement.h +++ b/src/solvers/refinement/string_refinement.h @@ -63,9 +63,6 @@ class string_refinementt: public bv_refinementt unsigned initial_loop_bound; - // Is the current model correct - bool concrete_model; - string_constraint_generatort generator; // Simple constraints that have been given to the solver From 6cc1266de12af40c9c1b852e5272a3c2aa82e872 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Mon, 27 Feb 2017 10:40:20 +0000 Subject: [PATCH 139/699] Adding refined_string_type to util Makefile --- src/util/Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/util/Makefile b/src/util/Makefile index e9dd739db8e..61cff93b9f0 100644 --- a/src/util/Makefile +++ b/src/util/Makefile @@ -23,7 +23,11 @@ SRC = arith_tools.cpp base_type.cpp cmdline.cpp config.cpp symbol_table.cpp \ memory_info.cpp pipe_stream.cpp irep_hash.cpp endianness_map.cpp \ ssa_expr.cpp json_irep.cpp json_expr.cpp \ fresh_symbol.cpp \ - format_number_range.cpp string_utils.cpp nondet_ifthenelse.cpp + format_number_range.cpp \ + nondet_ifthenelse.cpp \ + string_utils.cpp \ + refined_string_type.cpp \ + #Empty last line INCLUDES= -I .. From 402f8e180f04ffbf1ce73aad1ea9e084a3cb4837 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Tue, 10 Jan 2017 13:42:48 +0000 Subject: [PATCH 140/699] Adding string preprocessing of goto-programs to Makefile --- src/goto-programs/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/goto-programs/Makefile b/src/goto-programs/Makefile index 1b303c759b9..1d8ac6e1752 100644 --- a/src/goto-programs/Makefile +++ b/src/goto-programs/Makefile @@ -24,7 +24,8 @@ SRC = goto_convert.cpp goto_convert_function_call.cpp \ remove_instanceof.cpp \ class_identifier.cpp \ system_library_symbols.cpp \ - + string_refine_preprocess.cpp \ + # Empty last line INCLUDES= -I .. From 05582912383fd88e01e74a6b1107d2f18d46ee76 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Tue, 10 Jan 2017 13:43:30 +0000 Subject: [PATCH 141/699] Adding string solver cpp files to Makefile --- src/solvers/Makefile | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/solvers/Makefile b/src/solvers/Makefile index 95ea7650274..136db5765c1 100644 --- a/src/solvers/Makefile +++ b/src/solvers/Makefile @@ -118,6 +118,17 @@ SRC = $(CHAFF_SRC) $(BOOLEFORCE_SRC) $(MINISAT_SRC) $(MINISAT2_SRC) \ floatbv/float_utils.cpp floatbv/float_bv.cpp \ refinement/bv_refinement_loop.cpp refinement/refine_arithmetic.cpp \ refinement/refine_arrays.cpp \ + refinement/string_refinement.cpp \ + refinement/string_constraint_generator_code_points.cpp \ + refinement/string_constraint_generator_comparison.cpp \ + refinement/string_constraint_generator_concat.cpp \ + refinement/string_constraint_generator_constants.cpp \ + refinement/string_constraint_generator_indexof.cpp \ + refinement/string_constraint_generator_insert.cpp \ + refinement/string_constraint_generator_main.cpp \ + refinement/string_constraint_generator_testing.cpp \ + refinement/string_constraint_generator_transformation.cpp \ + refinement/string_constraint_generator_valueof.cpp \ miniBDD/miniBDD.cpp INCLUDES += -I .. \ From c7328e225f1e00e34aff9afe3067e4dfd02d30e9 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Tue, 10 Jan 2017 13:36:33 +0000 Subject: [PATCH 142/699] Adding the string refinement option to the CBMC solvers We add the option `--string-refine` which can be used to activate the string solver, in order to deal precisely with string functions. --- src/cbmc/cbmc_parse_options.cpp | 15 +++++++++++++++ src/cbmc/cbmc_parse_options.h | 1 + src/cbmc/cbmc_solvers.cpp | 24 ++++++++++++++++++++++++ src/cbmc/cbmc_solvers.h | 13 ++++++++----- 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/src/cbmc/cbmc_parse_options.cpp b/src/cbmc/cbmc_parse_options.cpp index e33e700e0ca..b6a96d1e178 100644 --- a/src/cbmc/cbmc_parse_options.cpp +++ b/src/cbmc/cbmc_parse_options.cpp @@ -20,6 +20,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include #include #include #include @@ -310,6 +311,11 @@ void cbmc_parse_optionst::get_command_line_options(optionst &options) options.set_option("refine-arithmetic", true); } + if(cmdline.isset("string-refine")) + { + options.set_option("string-refine", true); + } + if(cmdline.isset("max-node-refinement")) options.set_option( "max-node-refinement", @@ -904,6 +910,14 @@ bool cbmc_parse_optionst::process_goto_program( status() << "Partial Inlining" << eom; goto_partial_inline(goto_functions, ns, ui_message_handler); + + if(cmdline.isset("string-refine")) + { + status() << "Preprocessing for string refinement" << eom; + string_refine_preprocesst( + symbol_table, goto_functions, ui_message_handler); + } + // remove returns, gcc vectors, complex remove_returns(symbol_table, goto_functions); remove_vector(symbol_table, goto_functions); @@ -1191,6 +1205,7 @@ void cbmc_parse_optionst::help() " --yices use Yices\n" " --z3 use Z3\n" " --refine use refinement procedure (experimental)\n" + " --string-refine use string refinement (experimental)\n" " --outfile filename output formula to given file\n" " --arrays-uf-never never turn arrays into uninterpreted functions\n" // NOLINT(*) " --arrays-uf-always always turn arrays into uninterpreted functions\n" // NOLINT(*) diff --git a/src/cbmc/cbmc_parse_options.h b/src/cbmc/cbmc_parse_options.h index a3fc5e7e7d3..c6ed41c1e6a 100644 --- a/src/cbmc/cbmc_parse_options.h +++ b/src/cbmc/cbmc_parse_options.h @@ -37,6 +37,7 @@ class optionst; "(no-sat-preprocessor)" \ "(no-pretty-names)(beautify)" \ "(dimacs)(refine)(max-node-refinement):(refine-arrays)(refine-arithmetic)"\ + "(string-refine)" \ "(aig)(16)(32)(64)(LP64)(ILP64)(LLP64)(ILP32)(LP32)" \ "(little-endian)(big-endian)" \ "(show-goto-functions)(show-loops)" \ diff --git a/src/cbmc/cbmc_solvers.cpp b/src/cbmc/cbmc_solvers.cpp index ccd660dc586..a72546a8d0c 100644 --- a/src/cbmc/cbmc_solvers.cpp +++ b/src/cbmc/cbmc_solvers.cpp @@ -14,6 +14,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include #include #include #include @@ -213,6 +214,29 @@ cbmc_solverst::solvert* cbmc_solverst::get_bv_refinement() /*******************************************************************\ +Function: cbmc_solverst::get_string_refinement + + Outputs: a solver for cbmc + + Purpose: the string refinement adds to the bit vector refinement + specifications for functions from the Java string library + +\*******************************************************************/ + +cbmc_solverst::solvert* cbmc_solverst::get_string_refinement() +{ + propt *prop; + prop=new satcheck_no_simplifiert(); + prop->set_message_handler(get_message_handler()); + + string_refinementt *string_refinement=new string_refinementt( + ns, *prop, MAX_NB_REFINEMENT); + string_refinement->set_ui(ui); + return new solvert(string_refinement, prop); +} + +/*******************************************************************\ + Function: cbmc_solverst::get_smt1 Inputs: diff --git a/src/cbmc/cbmc_solvers.h b/src/cbmc/cbmc_solvers.h index 42d47fcaed3..be4a0e0ccde 100644 --- a/src/cbmc/cbmc_solvers.h +++ b/src/cbmc/cbmc_solvers.h @@ -111,15 +111,17 @@ class cbmc_solverst:public messaget solvert *solver; if(options.get_bool_option("dimacs")) - solver = get_dimacs(); + solver=get_dimacs(); else if(options.get_bool_option("refine")) - solver = get_bv_refinement(); + solver=get_bv_refinement(); + else if(options.get_bool_option("string-refine")) + solver=get_string_refinement(); else if(options.get_bool_option("smt1")) - solver = get_smt1(get_smt1_solver_type()); + solver=get_smt1(get_smt1_solver_type()); else if(options.get_bool_option("smt2")) - solver = get_smt2(get_smt2_solver_type()); + solver=get_smt2(get_smt2_solver_type()); else - solver = get_default(); + solver=get_default(); return std::unique_ptr(solver); } @@ -141,6 +143,7 @@ class cbmc_solverst:public messaget solvert *get_default(); solvert *get_dimacs(); solvert *get_bv_refinement(); + solvert *get_string_refinement(); solvert *get_smt1(smt1_dect::solvert solver); solvert *get_smt2(smt2_dect::solvert solver); From 9d2a1158dd4ff7f42083efcf47c80b8b1bc6b947 Mon Sep 17 00:00:00 2001 From: Joel Allred Date: Thu, 23 Mar 2017 18:18:14 +0000 Subject: [PATCH 143/699] Change option name to --refine-strings --- src/cbmc/cbmc_parse_options.cpp | 8 ++++---- src/cbmc/cbmc_parse_options.h | 2 +- src/cbmc/cbmc_solvers.h | 2 +- src/java_bytecode/java_bytecode_language.cpp | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cbmc/cbmc_parse_options.cpp b/src/cbmc/cbmc_parse_options.cpp index b6a96d1e178..b90afbb307e 100644 --- a/src/cbmc/cbmc_parse_options.cpp +++ b/src/cbmc/cbmc_parse_options.cpp @@ -311,9 +311,9 @@ void cbmc_parse_optionst::get_command_line_options(optionst &options) options.set_option("refine-arithmetic", true); } - if(cmdline.isset("string-refine")) + if(cmdline.isset("refine-strings")) { - options.set_option("string-refine", true); + options.set_option("refine-strings", true); } if(cmdline.isset("max-node-refinement")) @@ -911,7 +911,7 @@ bool cbmc_parse_optionst::process_goto_program( goto_partial_inline(goto_functions, ns, ui_message_handler); - if(cmdline.isset("string-refine")) + if(cmdline.isset("refine-strings")) { status() << "Preprocessing for string refinement" << eom; string_refine_preprocesst( @@ -1205,7 +1205,7 @@ void cbmc_parse_optionst::help() " --yices use Yices\n" " --z3 use Z3\n" " --refine use refinement procedure (experimental)\n" - " --string-refine use string refinement (experimental)\n" + " --refine-strings use string refinement (experimental)\n" " --outfile filename output formula to given file\n" " --arrays-uf-never never turn arrays into uninterpreted functions\n" // NOLINT(*) " --arrays-uf-always always turn arrays into uninterpreted functions\n" // NOLINT(*) diff --git a/src/cbmc/cbmc_parse_options.h b/src/cbmc/cbmc_parse_options.h index c6ed41c1e6a..266984c5c17 100644 --- a/src/cbmc/cbmc_parse_options.h +++ b/src/cbmc/cbmc_parse_options.h @@ -37,7 +37,7 @@ class optionst; "(no-sat-preprocessor)" \ "(no-pretty-names)(beautify)" \ "(dimacs)(refine)(max-node-refinement):(refine-arrays)(refine-arithmetic)"\ - "(string-refine)" \ + "(refine-strings)" \ "(aig)(16)(32)(64)(LP64)(ILP64)(LLP64)(ILP32)(LP32)" \ "(little-endian)(big-endian)" \ "(show-goto-functions)(show-loops)" \ diff --git a/src/cbmc/cbmc_solvers.h b/src/cbmc/cbmc_solvers.h index be4a0e0ccde..c837bd55806 100644 --- a/src/cbmc/cbmc_solvers.h +++ b/src/cbmc/cbmc_solvers.h @@ -114,7 +114,7 @@ class cbmc_solverst:public messaget solver=get_dimacs(); else if(options.get_bool_option("refine")) solver=get_bv_refinement(); - else if(options.get_bool_option("string-refine")) + else if(options.get_bool_option("refine-strings")) solver=get_string_refinement(); else if(options.get_bool_option("smt1")) solver=get_smt1(get_smt1_solver_type()); diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index 9faa16f676a..8ab88cf9dc6 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -44,7 +44,7 @@ void java_bytecode_languaget::get_language_options(const cmdlinet &cmd) { disable_runtime_checks=cmd.isset("disable-runtime-check"); assume_inputs_non_null=cmd.isset("java-assume-inputs-non-null"); - string_refinement_enabled=cmd.isset("string-refine"); + string_refinement_enabled=cmd.isset("refine-strings"); if(cmd.isset("java-max-input-array-length")) max_nondet_array_length= std::stoi(cmd.get_value("java-max-input-array-length")); From c7691a4ffd6a4075df7e0b1976e2a3b472be211b Mon Sep 17 00:00:00 2001 From: Joel Allred Date: Fri, 24 Feb 2017 17:36:40 +0000 Subject: [PATCH 144/699] Restructuration of tests on strings Add test java_intern Adapt test.desc to new output format Make more robust java tests. Add test for parseint. Correction in the hacks to use refined strings in C programs Add smoke tests for java string support Quick set of tests. Created by modifying the existing development tests. Longer tests are run when using 'make testall'. Format of java files was adapted. No change to the validation tests (written by Lucas Cordeiro). Update smoke tests Add a series of performance tests that check that the negation of the assertions found in the smoke tests indeed fail. Update java_char_array_init/test_init.class Add first fixed_bugs test For bug #95 Update test description with new option name String refinement option name has changed to --refine-strings Formatting in cprover-string-hack.h Move smoke tests to regression folder. Move fixed bugs tests to strings folder Move string perfomance tests to strings directory These are not really performance tests, only tests that are longer than the smoke tests. Adapt Makefile for new location of smoke tests --- regression/strings-smoke-tests/Makefile | 9 ++ .../java_append_char/test.desc | 7 ++ .../java_append_char/test_append_char.class | Bin 0 -> 999 bytes .../java_append_char/test_append_char.java | 17 ++++ .../java_append_int/test.desc | 7 ++ .../java_append_int/test_append_int.class | Bin 0 -> 842 bytes .../java_append_int/test_append_int.java | 11 +++ .../java_append_object/test.desc | 7 ++ .../test_append_object.class | Bin 0 -> 992 bytes .../test_append_object.java | 17 ++++ .../java_append_string/test.desc | 7 ++ .../test_append_string.class | Bin 0 -> 1032 bytes .../test_append_string.java | 14 +++ .../strings-smoke-tests/java_case/test.desc | 7 ++ .../java_case/test_case.class | Bin 0 -> 865 bytes .../java_case/test_case.java | 12 +++ .../java_char_array/test.desc | 7 ++ .../java_char_array/test_char_array.class | Bin 0 -> 714 bytes .../java_char_array/test_char_array.java | 13 +++ .../java_char_array_init/test.desc | 7 ++ .../java_char_array_init/test_init.class | Bin 0 -> 1046 bytes .../java_char_array_init/test_init.java | 21 ++++ .../java_char_at/test.desc | 7 ++ .../java_char_at/test_char_at.class | Bin 0 -> 628 bytes .../java_char_at/test_char_at.java | 7 ++ .../java_code_point/test.desc | 7 ++ .../java_code_point/test_code_point.class | Bin 0 -> 999 bytes .../java_code_point/test_code_point.java | 14 +++ .../java_compare/test.desc | 7 ++ .../java_compare/test_compare.class | Bin 0 -> 623 bytes .../java_compare/test_compare.java | 9 ++ .../strings-smoke-tests/java_concat/test.desc | 8 ++ .../java_concat/test_concat.class | Bin 0 -> 798 bytes .../java_concat/test_concat.java | 13 +++ .../java_contains/test.desc | 8 ++ .../java_contains/test_contains.class | Bin 0 -> 716 bytes .../java_contains/test_contains.java | 11 +++ .../strings-smoke-tests/java_delete/test.desc | 7 ++ .../java_delete/test_delete.class | Bin 0 -> 943 bytes .../java_delete/test_delete.java | 10 ++ .../java_delete_char_at/test.desc | 7 ++ .../test_delete_char_at.class | Bin 0 -> 867 bytes .../test_delete_char_at.java | 11 +++ .../strings-smoke-tests/java_empty/test.desc | 7 ++ .../java_empty/test_empty.class | Bin 0 -> 571 bytes .../java_empty/test_empty.java | 8 ++ .../java_endswith/test.desc | 8 ++ .../java_endswith/test_endswith.class | Bin 0 -> 711 bytes .../java_endswith/test_endswith.java | 12 +++ .../strings-smoke-tests/java_equal/test.desc | 8 ++ .../java_equal/test_equal.class | Bin 0 -> 725 bytes .../java_equal/test_equal.java | 11 +++ .../strings-smoke-tests/java_float/test.desc | 7 ++ .../java_float/test_float.class | Bin 0 -> 965 bytes .../java_float/test_float.java | 15 +++ .../java_hash_code/test.desc | 8 ++ .../java_hash_code/test_hash_code.class | Bin 0 -> 650 bytes .../java_hash_code/test_hash_code.java | 11 +++ .../java_index_of/test.desc | 7 ++ .../java_index_of/test_index_of.class | Bin 0 -> 631 bytes .../java_index_of/test_index_of.java | 10 ++ .../java_index_of_char/test.desc | 7 ++ .../test_index_of_char.class | Bin 0 -> 614 bytes .../test_index_of_char.java | 10 ++ .../java_insert_char/test.desc | 7 ++ .../java_insert_char/test_insert_char.class | Bin 0 -> 811 bytes .../java_insert_char/test_insert_char.java | 10 ++ .../java_insert_char_array/test.desc | 7 ++ .../test_insert_char_array.class | Bin 0 -> 979 bytes .../test_insert_char_array.java | 14 +++ .../java_insert_int/test.desc | 7 ++ .../java_insert_int/test_insert_int.class | Bin 0 -> 810 bytes .../java_insert_int/test_insert_int.java | 10 ++ .../.test_insert.java.swp | Bin 0 -> 12288 bytes .../java_insert_multiple/test.desc | 7 ++ .../test_insert_multiple.class | Bin 0 -> 898 bytes .../test_insert_multiple.java | 11 +++ .../java_insert_string/test.desc | 7 ++ .../test_insert_string.class | Bin 0 -> 841 bytes .../test_insert_string.java | 10 ++ .../java_int_to_string/test.desc | 7 ++ .../java_int_to_string/test_int.class | Bin 0 -> 859 bytes .../java_int_to_string/test_int.java | 11 +++ .../strings-smoke-tests/java_intern/test.desc | 7 ++ .../java_intern/test_intern.class | Bin 0 -> 634 bytes .../java_intern/test_intern.java | 11 +++ .../java_last_index_of/test.desc | 7 ++ .../test_last_index_of.class | Bin 0 -> 647 bytes .../test_last_index_of.java | 10 ++ .../java_last_index_of_char/test.desc | 7 ++ .../test_last_index_of_char.class | Bin 0 -> 623 bytes .../test_last_index_of_char.java | 9 ++ .../strings-smoke-tests/java_length/test.desc | 7 ++ .../java_length/test_length.class | Bin 0 -> 630 bytes .../java_length/test_length.java | 9 ++ .../java_parseint/test.desc | 8 ++ .../java_parseint/test_parseint.class | Bin 0 -> 727 bytes .../java_parseint/test_parseint.java | 10 ++ .../java_replace/test.desc | 7 ++ .../java_replace/test_replace.class | Bin 0 -> 980 bytes .../java_replace/test_replace.java | 13 +++ .../java_replace_char/test.desc | 7 ++ .../java_replace_char/test_replace_char.class | Bin 0 -> 730 bytes .../java_replace_char/test_replace_char.java | 9 ++ .../java_set_char_at/test.desc | 7 ++ .../java_set_char_at/test_set_char_at.class | Bin 0 -> 874 bytes .../java_set_char_at/test_set_char_at.java | 13 +++ .../java_set_length/test.desc | 9 ++ .../java_set_length/test_set_length.class | Bin 0 -> 861 bytes .../java_set_length/test_set_length.java | 12 +++ .../java_starts_with/test.desc | 8 ++ .../java_starts_with/test_starts_with.class | Bin 0 -> 719 bytes .../java_starts_with/test_starts_with.java | 11 +++ .../java_string_builder_length/test.desc | 7 ++ .../test_sb_length.class | Bin 0 -> 722 bytes .../test_sb_length.java | 9 ++ .../java_subsequence/test.desc | 7 ++ .../java_subsequence/test_subsequence.class | Bin 0 -> 789 bytes .../java_subsequence/test_subsequence.java | 14 +++ .../java_substring/test.desc | 7 ++ .../java_substring/test_substring.class | Bin 0 -> 740 bytes .../java_substring/test_substring.java | 14 +++ .../strings-smoke-tests/java_trim/test.desc | 8 ++ .../java_trim/test_trim.class | Bin 0 -> 641 bytes .../java_trim/test_trim.java | 9 ++ regression/strings/RegexMatches01/test.desc | 2 +- regression/strings/RegexMatches02/test.desc | 2 +- .../strings/RegexSubstitution01/test.desc | 2 +- .../strings/RegexSubstitution02/test.desc | 2 +- .../strings/RegexSubstitution03/test.desc | 2 +- .../strings/StaticCharMethods01/test.desc | 2 +- .../strings/StaticCharMethods02/test.desc | 2 +- .../strings/StaticCharMethods03/test.desc | 2 +- .../strings/StaticCharMethods04/test.desc | 2 +- .../strings/StaticCharMethods05/test.desc | 2 +- .../strings/StaticCharMethods06/test.desc | 2 +- .../strings/StringBuilderAppend01/test.desc | 2 +- .../strings/StringBuilderAppend02/test.desc | 2 +- .../strings/StringBuilderCapLen01/test.desc | 2 +- .../strings/StringBuilderCapLen02/test.desc | 2 +- .../strings/StringBuilderCapLen03/test.desc | 2 +- .../strings/StringBuilderCapLen04/test.desc | 2 +- .../strings/StringBuilderChars01/test.desc | 2 +- .../strings/StringBuilderChars02/test.desc | 2 +- .../strings/StringBuilderChars03/test.desc | 2 +- .../strings/StringBuilderChars04/test.desc | 2 +- .../strings/StringBuilderChars05/test.desc | 2 +- .../strings/StringBuilderChars06/test.desc | 2 +- .../StringBuilderConstructors01/test.desc | 2 +- .../StringBuilderConstructors02/test.desc | 2 +- .../StringBuilderInsertDelete01/test.desc | 2 +- .../StringBuilderInsertDelete02/test.desc | 2 +- .../StringBuilderInsertDelete03/test.desc | 2 +- regression/strings/StringCompare01/test.desc | 2 +- regression/strings/StringCompare02/test.desc | 2 +- regression/strings/StringCompare03/test.desc | 2 +- regression/strings/StringCompare04/test.desc | 2 +- regression/strings/StringCompare05/test.desc | 2 +- .../strings/StringConcatenation01/test.desc | 2 +- .../strings/StringConcatenation02/test.desc | 2 +- .../strings/StringConcatenation03/test.desc | 2 +- .../strings/StringConcatenation04/test.desc | 2 +- .../strings/StringConstructors01/test.desc | 2 +- .../strings/StringConstructors02/test.desc | 2 +- .../strings/StringConstructors03/test.desc | 2 +- .../strings/StringConstructors04/test.desc | 2 +- .../strings/StringConstructors05/test.desc | 2 +- .../strings/StringIndexMethods01/test.desc | 2 +- .../strings/StringIndexMethods02/test.desc | 2 +- .../strings/StringIndexMethods03/test.desc | 2 +- .../strings/StringIndexMethods04/test.desc | 2 +- .../strings/StringIndexMethods05/test.desc | 2 +- .../strings/StringMiscellaneous01/test.desc | 2 +- .../strings/StringMiscellaneous02/test.desc | 2 +- .../strings/StringMiscellaneous03/test.desc | 2 +- .../strings/StringMiscellaneous04/test.desc | 2 +- regression/strings/StringStartEnd01/test.desc | 2 +- regression/strings/StringStartEnd02/test.desc | 2 +- regression/strings/StringStartEnd03/test.desc | 2 +- regression/strings/StringValueOf01/test.desc | 2 +- regression/strings/StringValueOf02/test.desc | 2 +- regression/strings/StringValueOf03/test.desc | 2 +- regression/strings/StringValueOf04/test.desc | 2 +- regression/strings/StringValueOf05/test.desc | 2 +- regression/strings/StringValueOf06/test.desc | 2 +- regression/strings/StringValueOf07/test.desc | 2 +- regression/strings/StringValueOf08/test.desc | 2 +- regression/strings/StringValueOf09/test.desc | 2 +- regression/strings/StringValueOf10/test.desc | 2 +- regression/strings/SubString01/test.desc | 2 +- regression/strings/SubString02/test.desc | 2 +- regression/strings/SubString03/test.desc | 2 +- regression/strings/TokenTest01/test.desc | 2 +- regression/strings/TokenTest02/test.desc | 2 +- regression/strings/Validate01/test.desc | 2 +- regression/strings/Validate02/test.desc | 2 +- .../strings/bug-test-gen-095/test.class | Bin 0 -> 822 bytes regression/strings/bug-test-gen-095/test.desc | 7 ++ regression/strings/bug-test-gen-095/test.java | 10 ++ regression/strings/cprover-string-hack.h | 90 ++++++++++++------ regression/strings/java_append_char/test.desc | 7 ++ .../java_append_char/test_append_char.class | Bin 0 -> 999 bytes .../java_append_char/test_append_char.java | 17 ++++ regression/strings/java_append_int/test.desc | 7 ++ .../java_append_int/test_append_int.class | Bin 0 -> 842 bytes .../java_append_int/test_append_int.java | 11 +++ .../strings/java_append_object/test.desc | 7 ++ .../test_append_object.class | Bin 0 -> 992 bytes .../test_append_object.java | 17 ++++ .../strings/java_append_string/test.desc | 7 ++ .../test_append_string.class | Bin 0 -> 1032 bytes .../test_append_string.java | 14 +++ regression/strings/java_case/test.desc | 7 +- regression/strings/java_case/test_case.class | Bin 1073 -> 839 bytes regression/strings/java_case/test_case.java | 26 +++-- regression/strings/java_char_array/test.desc | 6 +- .../java_char_array/test_char_array.class | Bin 820 -> 676 bytes .../java_char_array/test_char_array.java | 26 +++-- .../strings/java_char_array_init/test.desc | 8 +- .../java_char_array_init/test_init.class | Bin 1209 -> 836 bytes .../java_char_array_init/test_init.java | 33 +++---- regression/strings/java_char_at/test.desc | 6 +- .../strings/java_char_at/test_char_at.class | Bin 951 -> 628 bytes .../strings/java_char_at/test_char_at.java | 18 +--- regression/strings/java_code_point/test.desc | 10 +- .../java_code_point/test_code_point.class | Bin 1025 -> 941 bytes .../java_code_point/test_code_point.java | 25 ++--- regression/strings/java_compare/test.desc | 7 +- .../strings/java_compare/test_compare.class | Bin 780 -> 623 bytes .../strings/java_compare/test_compare.java | 25 ++--- regression/strings/java_concat/test.desc | 6 +- .../strings/java_concat/test_concat.class | Bin 854 -> 798 bytes .../strings/java_concat/test_concat.java | 23 ++--- regression/strings/java_contains/test.desc | 5 +- .../strings/java_contains/test_contains.class | Bin 753 -> 671 bytes .../strings/java_contains/test_contains.java | 17 ++-- regression/strings/java_delete/test.desc | 5 +- .../strings/java_delete/test_delete.class | Bin 1126 -> 800 bytes .../strings/java_delete/test_delete.java | 23 ++--- .../strings/java_delete_char_at/test.desc | 7 ++ .../test_delete_char_at.class | Bin 0 -> 867 bytes .../test_delete_char_at.java | 11 +++ .../strings/java_easychair/easychair.class | Bin 1164 -> 1163 bytes .../strings/java_easychair/easychair.java | 62 ++++++------ regression/strings/java_easychair/test.desc | 6 +- regression/strings/java_empty/test.desc | 5 +- .../strings/java_empty/test_empty.class | Bin 669 -> 571 bytes regression/strings/java_empty/test_empty.java | 13 +-- regression/strings/java_endswith/test.desc | 7 ++ .../strings/java_endswith/test_endswith.class | Bin 0 -> 666 bytes .../strings/java_endswith/test_endswith.java | 9 ++ regression/strings/java_equal/test.desc | 5 +- .../strings/java_equal/test_equal.class | Bin 726 -> 725 bytes regression/strings/java_equal/test_equal.java | 17 ++-- regression/strings/java_float/test.desc | 7 +- .../strings/java_float/test_float.class | Bin 1095 -> 1015 bytes regression/strings/java_float/test_float.java | 35 ++++--- regression/strings/java_hash_code/test.desc | 7 ++ .../java_hash_code/test_hash_code.class | Bin 0 -> 602 bytes .../java_hash_code/test_hash_code.java | 9 ++ regression/strings/java_index_of/test.desc | 13 +-- .../strings/java_index_of/test_index_of.class | Bin 1108 -> 631 bytes .../strings/java_index_of/test_index_of.java | 40 ++------ .../strings/java_index_of_char/test.desc | 7 ++ .../test_index_of_char.class | Bin 0 -> 614 bytes .../test_index_of_char.java | 10 ++ .../strings/java_insert/test_insert.class | Bin 1318 -> 0 bytes .../strings/java_insert/test_insert.java | 19 ---- .../strings/java_insert/test_insert1.class | Bin 1035 -> 0 bytes .../strings/java_insert/test_insert1.java | 23 ----- regression/strings/java_insert_char/test.desc | 7 ++ .../java_insert_char/test_insert_char.class | Bin 0 -> 811 bytes .../java_insert_char/test_insert_char.java | 10 ++ .../strings/java_insert_char_array/test.desc | 7 ++ .../test_insert_char_array.class | Bin 0 -> 979 bytes .../test_insert_char_array.java | 14 +++ regression/strings/java_insert_int/test.desc | 7 ++ .../java_insert_int/test_insert_int.class | Bin 0 -> 810 bytes .../java_insert_int/test_insert_int.java | 10 ++ .../strings/java_insert_multiple/test.desc | 7 ++ .../test_insert_multiple.class | Bin 0 -> 898 bytes .../test_insert_multiple.java | 11 +++ .../strings/java_insert_string/test.desc | 7 ++ .../test_insert_string.class | Bin 0 -> 841 bytes .../test_insert_string.java | 10 ++ regression/strings/java_int/test.desc | 13 --- regression/strings/java_int/test_int.class | Bin 1140 -> 0 bytes regression/strings/java_int/test_int.java | 25 ----- regression/strings/java_prefix/test.desc | 10 -- .../strings/java_prefix/test_prefix.class | Bin 933 -> 0 bytes .../strings/java_prefix/test_prefix.java | 23 ----- regression/strings/java_replace/test.desc | 8 -- .../strings/java_replace/test_replace.class | Bin 904 -> 0 bytes .../strings/java_replace/test_replace.java | 10 -- regression/strings/java_set_length/test.desc | 9 -- .../java_set_length/test_set_length.class | Bin 887 -> 0 bytes .../java_set_length/test_set_length.java | 12 --- .../strings/java_string_builder/test.desc | 9 -- .../test_string_builder.class | Bin 1003 -> 0 bytes .../test_string_builder.java | 16 ---- .../java_string_builder_insert/test.desc | 8 -- .../test_insert.class | Bin 1049 -> 0 bytes .../test_insert.java | 20 ---- .../java_string_builder_length/test.desc | 8 -- .../test_sb_length.class | Bin 791 -> 0 bytes .../test_sb_length.java | 11 --- regression/strings/java_strlen/test.desc | 8 -- .../strings/java_strlen/test_length.class | Bin 864 -> 0 bytes .../strings/java_strlen/test_length.java | 14 --- regression/strings/java_substring/test.desc | 10 -- .../java_substring/test_substring.class | Bin 1051 -> 0 bytes .../java_substring/test_substring.java | 27 ------ regression/strings/java_suffix/test.desc | 8 -- .../strings/java_suffix/test_suffix.class | Bin 811 -> 0 bytes .../strings/java_suffix/test_suffix.java | 15 --- regression/strings/java_trim/test.desc | 8 -- regression/strings/java_trim/test_trim.class | Bin 730 -> 0 bytes regression/strings/java_trim/test_trim.java | 8 -- regression/strings/test1/test.desc | 2 +- regression/strings/test2/test.desc | 2 +- regression/strings/test3.1/test.desc | 2 +- regression/strings/test3.2/test.desc | 2 +- regression/strings/test3.3/test.desc | 2 +- regression/strings/test3.4/test.desc | 8 +- regression/strings/test3/test.desc | 2 +- regression/strings/test4/test.desc | 2 +- regression/strings/test5/test.desc | 2 +- regression/strings/test_char_set/test.desc | 6 +- regression/strings/test_concat/test.desc | 2 +- regression/strings/test_contains/test.desc | 2 +- regression/strings/test_equal/test.desc | 6 +- regression/strings/test_index_of/test.desc | 2 +- regression/strings/test_int/test.desc | 2 +- regression/strings/test_pass1/test.desc | 2 +- regression/strings/test_pass_pc3/test.desc | 2 +- regression/strings/test_prefix/test.desc | 2 +- regression/strings/test_strlen/test.desc | 2 +- regression/strings/test_substring/test.desc | 10 +- regression/strings/test_suffix/test.desc | 2 +- 339 files changed, 1402 insertions(+), 738 deletions(-) create mode 100644 regression/strings-smoke-tests/Makefile create mode 100644 regression/strings-smoke-tests/java_append_char/test.desc create mode 100644 regression/strings-smoke-tests/java_append_char/test_append_char.class create mode 100644 regression/strings-smoke-tests/java_append_char/test_append_char.java create mode 100644 regression/strings-smoke-tests/java_append_int/test.desc create mode 100644 regression/strings-smoke-tests/java_append_int/test_append_int.class create mode 100644 regression/strings-smoke-tests/java_append_int/test_append_int.java create mode 100644 regression/strings-smoke-tests/java_append_object/test.desc create mode 100644 regression/strings-smoke-tests/java_append_object/test_append_object.class create mode 100644 regression/strings-smoke-tests/java_append_object/test_append_object.java create mode 100644 regression/strings-smoke-tests/java_append_string/test.desc create mode 100644 regression/strings-smoke-tests/java_append_string/test_append_string.class create mode 100644 regression/strings-smoke-tests/java_append_string/test_append_string.java create mode 100644 regression/strings-smoke-tests/java_case/test.desc create mode 100644 regression/strings-smoke-tests/java_case/test_case.class create mode 100644 regression/strings-smoke-tests/java_case/test_case.java create mode 100644 regression/strings-smoke-tests/java_char_array/test.desc create mode 100644 regression/strings-smoke-tests/java_char_array/test_char_array.class create mode 100644 regression/strings-smoke-tests/java_char_array/test_char_array.java create mode 100644 regression/strings-smoke-tests/java_char_array_init/test.desc create mode 100644 regression/strings-smoke-tests/java_char_array_init/test_init.class create mode 100644 regression/strings-smoke-tests/java_char_array_init/test_init.java create mode 100644 regression/strings-smoke-tests/java_char_at/test.desc create mode 100644 regression/strings-smoke-tests/java_char_at/test_char_at.class create mode 100644 regression/strings-smoke-tests/java_char_at/test_char_at.java create mode 100644 regression/strings-smoke-tests/java_code_point/test.desc create mode 100644 regression/strings-smoke-tests/java_code_point/test_code_point.class create mode 100644 regression/strings-smoke-tests/java_code_point/test_code_point.java create mode 100644 regression/strings-smoke-tests/java_compare/test.desc create mode 100644 regression/strings-smoke-tests/java_compare/test_compare.class create mode 100644 regression/strings-smoke-tests/java_compare/test_compare.java create mode 100644 regression/strings-smoke-tests/java_concat/test.desc create mode 100644 regression/strings-smoke-tests/java_concat/test_concat.class create mode 100644 regression/strings-smoke-tests/java_concat/test_concat.java create mode 100644 regression/strings-smoke-tests/java_contains/test.desc create mode 100644 regression/strings-smoke-tests/java_contains/test_contains.class create mode 100644 regression/strings-smoke-tests/java_contains/test_contains.java create mode 100644 regression/strings-smoke-tests/java_delete/test.desc create mode 100644 regression/strings-smoke-tests/java_delete/test_delete.class create mode 100644 regression/strings-smoke-tests/java_delete/test_delete.java create mode 100644 regression/strings-smoke-tests/java_delete_char_at/test.desc create mode 100644 regression/strings-smoke-tests/java_delete_char_at/test_delete_char_at.class create mode 100644 regression/strings-smoke-tests/java_delete_char_at/test_delete_char_at.java create mode 100644 regression/strings-smoke-tests/java_empty/test.desc create mode 100644 regression/strings-smoke-tests/java_empty/test_empty.class create mode 100644 regression/strings-smoke-tests/java_empty/test_empty.java create mode 100644 regression/strings-smoke-tests/java_endswith/test.desc create mode 100644 regression/strings-smoke-tests/java_endswith/test_endswith.class create mode 100644 regression/strings-smoke-tests/java_endswith/test_endswith.java create mode 100644 regression/strings-smoke-tests/java_equal/test.desc create mode 100644 regression/strings-smoke-tests/java_equal/test_equal.class create mode 100644 regression/strings-smoke-tests/java_equal/test_equal.java create mode 100644 regression/strings-smoke-tests/java_float/test.desc create mode 100644 regression/strings-smoke-tests/java_float/test_float.class create mode 100644 regression/strings-smoke-tests/java_float/test_float.java create mode 100644 regression/strings-smoke-tests/java_hash_code/test.desc create mode 100644 regression/strings-smoke-tests/java_hash_code/test_hash_code.class create mode 100644 regression/strings-smoke-tests/java_hash_code/test_hash_code.java create mode 100644 regression/strings-smoke-tests/java_index_of/test.desc create mode 100644 regression/strings-smoke-tests/java_index_of/test_index_of.class create mode 100644 regression/strings-smoke-tests/java_index_of/test_index_of.java create mode 100644 regression/strings-smoke-tests/java_index_of_char/test.desc create mode 100644 regression/strings-smoke-tests/java_index_of_char/test_index_of_char.class create mode 100644 regression/strings-smoke-tests/java_index_of_char/test_index_of_char.java create mode 100644 regression/strings-smoke-tests/java_insert_char/test.desc create mode 100644 regression/strings-smoke-tests/java_insert_char/test_insert_char.class create mode 100644 regression/strings-smoke-tests/java_insert_char/test_insert_char.java create mode 100644 regression/strings-smoke-tests/java_insert_char_array/test.desc create mode 100644 regression/strings-smoke-tests/java_insert_char_array/test_insert_char_array.class create mode 100644 regression/strings-smoke-tests/java_insert_char_array/test_insert_char_array.java create mode 100644 regression/strings-smoke-tests/java_insert_int/test.desc create mode 100644 regression/strings-smoke-tests/java_insert_int/test_insert_int.class create mode 100644 regression/strings-smoke-tests/java_insert_int/test_insert_int.java create mode 100644 regression/strings-smoke-tests/java_insert_multiple/.test_insert.java.swp create mode 100644 regression/strings-smoke-tests/java_insert_multiple/test.desc create mode 100644 regression/strings-smoke-tests/java_insert_multiple/test_insert_multiple.class create mode 100644 regression/strings-smoke-tests/java_insert_multiple/test_insert_multiple.java create mode 100644 regression/strings-smoke-tests/java_insert_string/test.desc create mode 100644 regression/strings-smoke-tests/java_insert_string/test_insert_string.class create mode 100644 regression/strings-smoke-tests/java_insert_string/test_insert_string.java create mode 100644 regression/strings-smoke-tests/java_int_to_string/test.desc create mode 100644 regression/strings-smoke-tests/java_int_to_string/test_int.class create mode 100644 regression/strings-smoke-tests/java_int_to_string/test_int.java create mode 100644 regression/strings-smoke-tests/java_intern/test.desc create mode 100644 regression/strings-smoke-tests/java_intern/test_intern.class create mode 100644 regression/strings-smoke-tests/java_intern/test_intern.java create mode 100644 regression/strings-smoke-tests/java_last_index_of/test.desc create mode 100644 regression/strings-smoke-tests/java_last_index_of/test_last_index_of.class create mode 100644 regression/strings-smoke-tests/java_last_index_of/test_last_index_of.java create mode 100644 regression/strings-smoke-tests/java_last_index_of_char/test.desc create mode 100644 regression/strings-smoke-tests/java_last_index_of_char/test_last_index_of_char.class create mode 100644 regression/strings-smoke-tests/java_last_index_of_char/test_last_index_of_char.java create mode 100644 regression/strings-smoke-tests/java_length/test.desc create mode 100644 regression/strings-smoke-tests/java_length/test_length.class create mode 100644 regression/strings-smoke-tests/java_length/test_length.java create mode 100644 regression/strings-smoke-tests/java_parseint/test.desc create mode 100644 regression/strings-smoke-tests/java_parseint/test_parseint.class create mode 100644 regression/strings-smoke-tests/java_parseint/test_parseint.java create mode 100644 regression/strings-smoke-tests/java_replace/test.desc create mode 100644 regression/strings-smoke-tests/java_replace/test_replace.class create mode 100644 regression/strings-smoke-tests/java_replace/test_replace.java create mode 100644 regression/strings-smoke-tests/java_replace_char/test.desc create mode 100644 regression/strings-smoke-tests/java_replace_char/test_replace_char.class create mode 100644 regression/strings-smoke-tests/java_replace_char/test_replace_char.java create mode 100644 regression/strings-smoke-tests/java_set_char_at/test.desc create mode 100644 regression/strings-smoke-tests/java_set_char_at/test_set_char_at.class create mode 100644 regression/strings-smoke-tests/java_set_char_at/test_set_char_at.java create mode 100644 regression/strings-smoke-tests/java_set_length/test.desc create mode 100644 regression/strings-smoke-tests/java_set_length/test_set_length.class create mode 100644 regression/strings-smoke-tests/java_set_length/test_set_length.java create mode 100644 regression/strings-smoke-tests/java_starts_with/test.desc create mode 100644 regression/strings-smoke-tests/java_starts_with/test_starts_with.class create mode 100644 regression/strings-smoke-tests/java_starts_with/test_starts_with.java create mode 100644 regression/strings-smoke-tests/java_string_builder_length/test.desc create mode 100644 regression/strings-smoke-tests/java_string_builder_length/test_sb_length.class create mode 100644 regression/strings-smoke-tests/java_string_builder_length/test_sb_length.java create mode 100644 regression/strings-smoke-tests/java_subsequence/test.desc create mode 100644 regression/strings-smoke-tests/java_subsequence/test_subsequence.class create mode 100644 regression/strings-smoke-tests/java_subsequence/test_subsequence.java create mode 100644 regression/strings-smoke-tests/java_substring/test.desc create mode 100644 regression/strings-smoke-tests/java_substring/test_substring.class create mode 100644 regression/strings-smoke-tests/java_substring/test_substring.java create mode 100644 regression/strings-smoke-tests/java_trim/test.desc create mode 100644 regression/strings-smoke-tests/java_trim/test_trim.class create mode 100644 regression/strings-smoke-tests/java_trim/test_trim.java create mode 100644 regression/strings/bug-test-gen-095/test.class create mode 100644 regression/strings/bug-test-gen-095/test.desc create mode 100644 regression/strings/bug-test-gen-095/test.java create mode 100644 regression/strings/java_append_char/test.desc create mode 100644 regression/strings/java_append_char/test_append_char.class create mode 100644 regression/strings/java_append_char/test_append_char.java create mode 100644 regression/strings/java_append_int/test.desc create mode 100644 regression/strings/java_append_int/test_append_int.class create mode 100644 regression/strings/java_append_int/test_append_int.java create mode 100644 regression/strings/java_append_object/test.desc create mode 100644 regression/strings/java_append_object/test_append_object.class create mode 100644 regression/strings/java_append_object/test_append_object.java create mode 100644 regression/strings/java_append_string/test.desc create mode 100644 regression/strings/java_append_string/test_append_string.class create mode 100644 regression/strings/java_append_string/test_append_string.java create mode 100644 regression/strings/java_delete_char_at/test.desc create mode 100644 regression/strings/java_delete_char_at/test_delete_char_at.class create mode 100644 regression/strings/java_delete_char_at/test_delete_char_at.java create mode 100644 regression/strings/java_endswith/test.desc create mode 100644 regression/strings/java_endswith/test_endswith.class create mode 100644 regression/strings/java_endswith/test_endswith.java create mode 100644 regression/strings/java_hash_code/test.desc create mode 100644 regression/strings/java_hash_code/test_hash_code.class create mode 100644 regression/strings/java_hash_code/test_hash_code.java create mode 100644 regression/strings/java_index_of_char/test.desc create mode 100644 regression/strings/java_index_of_char/test_index_of_char.class create mode 100644 regression/strings/java_index_of_char/test_index_of_char.java delete mode 100644 regression/strings/java_insert/test_insert.class delete mode 100644 regression/strings/java_insert/test_insert.java delete mode 100644 regression/strings/java_insert/test_insert1.class delete mode 100644 regression/strings/java_insert/test_insert1.java create mode 100644 regression/strings/java_insert_char/test.desc create mode 100644 regression/strings/java_insert_char/test_insert_char.class create mode 100644 regression/strings/java_insert_char/test_insert_char.java create mode 100644 regression/strings/java_insert_char_array/test.desc create mode 100644 regression/strings/java_insert_char_array/test_insert_char_array.class create mode 100644 regression/strings/java_insert_char_array/test_insert_char_array.java create mode 100644 regression/strings/java_insert_int/test.desc create mode 100644 regression/strings/java_insert_int/test_insert_int.class create mode 100644 regression/strings/java_insert_int/test_insert_int.java create mode 100644 regression/strings/java_insert_multiple/test.desc create mode 100644 regression/strings/java_insert_multiple/test_insert_multiple.class create mode 100644 regression/strings/java_insert_multiple/test_insert_multiple.java create mode 100644 regression/strings/java_insert_string/test.desc create mode 100644 regression/strings/java_insert_string/test_insert_string.class create mode 100644 regression/strings/java_insert_string/test_insert_string.java delete mode 100644 regression/strings/java_int/test.desc delete mode 100644 regression/strings/java_int/test_int.class delete mode 100644 regression/strings/java_int/test_int.java delete mode 100644 regression/strings/java_prefix/test.desc delete mode 100644 regression/strings/java_prefix/test_prefix.class delete mode 100644 regression/strings/java_prefix/test_prefix.java delete mode 100644 regression/strings/java_replace/test.desc delete mode 100644 regression/strings/java_replace/test_replace.class delete mode 100644 regression/strings/java_replace/test_replace.java delete mode 100644 regression/strings/java_set_length/test.desc delete mode 100644 regression/strings/java_set_length/test_set_length.class delete mode 100644 regression/strings/java_set_length/test_set_length.java delete mode 100644 regression/strings/java_string_builder/test.desc delete mode 100644 regression/strings/java_string_builder/test_string_builder.class delete mode 100644 regression/strings/java_string_builder/test_string_builder.java delete mode 100644 regression/strings/java_string_builder_insert/test.desc delete mode 100644 regression/strings/java_string_builder_insert/test_insert.class delete mode 100644 regression/strings/java_string_builder_insert/test_insert.java delete mode 100644 regression/strings/java_string_builder_length/test.desc delete mode 100644 regression/strings/java_string_builder_length/test_sb_length.class delete mode 100644 regression/strings/java_string_builder_length/test_sb_length.java delete mode 100644 regression/strings/java_strlen/test.desc delete mode 100644 regression/strings/java_strlen/test_length.class delete mode 100644 regression/strings/java_strlen/test_length.java delete mode 100644 regression/strings/java_substring/test.desc delete mode 100644 regression/strings/java_substring/test_substring.class delete mode 100644 regression/strings/java_substring/test_substring.java delete mode 100644 regression/strings/java_suffix/test.desc delete mode 100644 regression/strings/java_suffix/test_suffix.class delete mode 100644 regression/strings/java_suffix/test_suffix.java delete mode 100644 regression/strings/java_trim/test.desc delete mode 100644 regression/strings/java_trim/test_trim.class delete mode 100644 regression/strings/java_trim/test_trim.java diff --git a/regression/strings-smoke-tests/Makefile b/regression/strings-smoke-tests/Makefile new file mode 100644 index 00000000000..c41ab1c5be8 --- /dev/null +++ b/regression/strings-smoke-tests/Makefile @@ -0,0 +1,9 @@ + +test: + @../test.pl -c ../../../src/cbmc/cbmc + +testfuture: + @../test.pl -c ../../../src/cbmc/cbmc -CF + +testall: + @../test.pl -c ../../../src/cbmc/cbmc -CFTK diff --git a/regression/strings-smoke-tests/java_append_char/test.desc b/regression/strings-smoke-tests/java_append_char/test.desc new file mode 100644 index 00000000000..0f1b3ae243f --- /dev/null +++ b/regression/strings-smoke-tests/java_append_char/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_append_char.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_append_char/test_append_char.class b/regression/strings-smoke-tests/java_append_char/test_append_char.class new file mode 100644 index 0000000000000000000000000000000000000000..00c40aef6f6514f718dc1137889e4124d8bd7230 GIT binary patch literal 999 zcmZWnYf}Wo2Pz(&a;H%@8%{2WMdqwzlljUYhBz_y_u& z&ES+xeeXwA?}3!mVR?7YbKcAIyzl$#_qQJa7O0Ha)#&34?)cGDMe5+w_+i!nyow z2BqW}f+4wP+F~PU)`a^?I@3i{H*JQ#vai?Qt?R80%uyg-9PEZyEIlzrEP5Y% z?TWh35ZWr8z`M+-Q(X}Z+1yqszt#&pLA^-ieCH@;ICs{OJpQX%{^3CdNX=QrVhY9OGl*1Mmr!w z93#iBU!l+sXz=fmYB*(7s!GbNR3oWIr5Yvkyo=W)Zb>|lxTvfhB2+y*hO46R8 z9~&f4khoFuN`w8OgTj&NJm)yh6CA^ZV;Kt_X~4i>UmN{<;L0Z`;V+2wDjunq86ya3 ME3!uy=@3HpFJ~^+h5!Hn literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_append_char/test_append_char.java b/regression/strings-smoke-tests/java_append_char/test_append_char.java new file mode 100644 index 00000000000..3eec4f30abe --- /dev/null +++ b/regression/strings-smoke-tests/java_append_char/test_append_char.java @@ -0,0 +1,17 @@ +public class test_append_char +{ + public static void main(/*String[] args*/) + { + char[] diff = {'d', 'i', 'f', 'f'}; + char[] blue = {'b', 'l', 'u', 'e'}; + + StringBuilder buffer = new StringBuilder(); + + buffer.append(diff) + .append(blue); + + String tmp=buffer.toString(); + System.out.println(tmp); + assert tmp.equals("diffblue"); + } +} diff --git a/regression/strings-smoke-tests/java_append_int/test.desc b/regression/strings-smoke-tests/java_append_int/test.desc new file mode 100644 index 00000000000..e1455859470 --- /dev/null +++ b/regression/strings-smoke-tests/java_append_int/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_append_int.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_append_int/test_append_int.class b/regression/strings-smoke-tests/java_append_int/test_append_int.class new file mode 100644 index 0000000000000000000000000000000000000000..16948397e03dc279cdae32b41c8692bcfbb44978 GIT binary patch literal 842 zcmaJfgc5Pjo(*l`@3rfC~W0~87*DQ!pza7cxK0upKphaf6?shoIKxwv+)9ezyy z0B1l-B`U$4{{&*zX&Rssmzmx9c<=4Z{`mFv8-OMr=rB=Maao6gvW6?tUzKKAnrj*4 za9zWSjvKhC;+BrAEU)OOqNZY%FuP)fp$H06*g4eQ`6GxWg5ptc#>b={s`f->gsklwhHhb= zJ{tlrC>n5r_qm5<{uw6!A%$q`b!HFbpaZfyj${TbR2#nnP)1bv9?39?*he3!UNjJwFlOa_g; z36*0S7MZ019SfYvf_|c*qNL(toSNut#)5#ELT-c$L#WA*NG85On_^EiOPmxGo@H<&=ME&u=k literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_append_int/test_append_int.java b/regression/strings-smoke-tests/java_append_int/test_append_int.java new file mode 100644 index 00000000000..963f3d7c063 --- /dev/null +++ b/regression/strings-smoke-tests/java_append_int/test_append_int.java @@ -0,0 +1,11 @@ +public class test_append_int +{ + public static void main(/*String[] args*/) + { + StringBuilder diffblue = new StringBuilder(); + diffblue.append("d"); + diffblue.append(4); + String s = diffblue.toString(); + assert s.equals("d4"); + } +} diff --git a/regression/strings-smoke-tests/java_append_object/test.desc b/regression/strings-smoke-tests/java_append_object/test.desc new file mode 100644 index 00000000000..5db2ac1db73 --- /dev/null +++ b/regression/strings-smoke-tests/java_append_object/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_append_object.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_append_object/test_append_object.class b/regression/strings-smoke-tests/java_append_object/test_append_object.class new file mode 100644 index 0000000000000000000000000000000000000000..ed6942a1fa6ddb20c36b528444d598e867e347f5 GIT binary patch literal 992 zcmZWn*>2N76g`t|9M@^mbPIb6p(Jh7u#`2SEAT>Ekb*$;rE=nF<>J`E3ld+!dwzgt zij+!Jf_FX&xZ{wfX=VG4=gygP&s~21`SBCLGB#C=VMf8Mg6kYNRKzeNOy5|YkHyzu1W_o(V5(Wd?VMtU>+w@l$ zqJ`pHhS;WK2!?dcw8eJNY6$m@1k*uFH*JPg-PfBRw)A%BCT`NjagRZ%Hm(0mYTXIk zrg&k>d(*z~{9V1>7PhhLG!8`5Upmk~=^7?5NwkK!w?|9E3M5#blr7!fFV}t7wD&gx z(=vpsQ8Dgocz}l-k2E~S6OM|8DxPY{Vw|E&8p%OgG^}8iAvfS!@8|y9bsd)>dtMXA znuc|3Fk}YzUWIapTs>J-wq8aIr9$oOg-Y?1YbcKjDfOK`$3)>gkPxQ?)IWQ^Xi;yR zz-O53(V9;AHPyx^8lku7!gwfP*v-J(5@b=&CQnQ31+U0nC&b4R*arn|^=z++z#i++bXh}h3bGR6_n)@0^aX%oS3C;sZb6 zvzWArB>L`05%-x=nuO#a7V$IhB!u~xT_+U z#5g82Rt39^(lGmdgsB>X^rZf@eAwv7}=eD^i=&(T@S*Y>9GN$12tsvh8v!tx;@v zp6f9fmsu)U*Rg@k4vw!6j(90x=+AApi#3VQ%h@HGjWSIAE8tSjc|Y?V7{$+iz$>&3 zwq1gq5#mx#O^o97HW(K7ygKXMT2g4@qkf9p5twCpU3$v|8snFx&xNnE=K{X(fx^1V1kWY>r`5PNxw_-+GtBn zT|1;t)}fyub&SlU(OpN+F}hBXrnKH)5-$?sjS&)&fJVp$6v9+-lWb#T$)gK1(6NOS zu2WPu*crAI3@NxlGK_4sGaK>-dJUtFzGEn{uZTszBh`j#wI)l&5z&|B0B+Gw1jBy- DqWB3A~sECS)t!#oa~!3s1iJ ztR|4yMBn{Ujc0ZRv^JTXnK|b>=ljl?`E~sL2Y@ObsYoF&vG34ZOeUXx<+Tfdkn125ZyK{(|gPy z6^d^d!gagH84?ZC;x9&r9qzmmUrp2(-^o;JiePigmNf?8&-5va?p*HQ2)8)@i zk+JM?*L&MFT)uf=d@wYmkzq)Rb7f#y{YukwOsmfj+Uba3MZ-9{$7mvU9+@9z&+kSdEEkp53rN za;HwR8PbK~|1cl)dN`bcqWt~H7`P{D21Hv$8gViJ?Dj3&;X&b3=?R)xh^i0h$r!Rd z?wSto&D*92@J1A%_iAH}K0%6p3QOk1$mk@2WFtd1OSe_p8SRnM6zq!t;tbiS@1$WN zH-~@)+r|u1pXcBYp(6HAVbq;NH-+)7&L}X@cdy z(1JhY^XDPcIYK`+N)5;)SV5W8)X3999A_z-gmjFujB~-tW(jkCuD0rT0HpN91j#Yv a@MnajZ;%%xvnEBc2twKuF^UVmhSlFL=B-Bn literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_case/test_case.java b/regression/strings-smoke-tests/java_case/test_case.java new file mode 100644 index 00000000000..b3437a6f83e --- /dev/null +++ b/regression/strings-smoke-tests/java_case/test_case.java @@ -0,0 +1,12 @@ +public class test_case +{ + public static void main(/*String[] argv*/) + { + String s = new String("Ab"); + String l = s.toLowerCase(); + String u = s.toUpperCase(); + assert(l.equals("ab")); + assert(u.equals("AB")); + assert(s.equalsIgnoreCase("aB")); + } +} diff --git a/regression/strings-smoke-tests/java_char_array/test.desc b/regression/strings-smoke-tests/java_char_array/test.desc new file mode 100644 index 00000000000..ecce56c1ab8 --- /dev/null +++ b/regression/strings-smoke-tests/java_char_array/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_char_array.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_char_array/test_char_array.class b/regression/strings-smoke-tests/java_char_array/test_char_array.class new file mode 100644 index 0000000000000000000000000000000000000000..0d2056042ca2ef3063d717972cfe8bf0f7b0d053 GIT binary patch literal 714 zcmZXR%Wl&^6o&t?9gpL zsgPK*2BcI1sqA?u;EbUOm(7`(|J=TF=G*trX8=05?ZQRP!6g@$aYdV@A{^8?uDY;M zAm|?D;iSXr9@hX=&Zg8wJI2+;UcNw>zj8!NfMLKCAlWBGkz7Xm_C?($9 zITEjhhdInsKQRa?-@{F;dANm!hY~!7nvPi?iTH56d(Qk&sYDUgKjk=@9$IKK__L&) z!I2EJzodSqqWF-(*zYlvvZO~qUCl#dHJVzqHDi~utj6Oez00$Dy%DXBVR0zaNXg-p zi58KK$w7PD!!m8&rEg(=O;15L6SOSMlP%M$PA8+Y&^iVCpabEPwR4f7h{`ndEeu%X z+o>8)S`(OC?Ly~X%bdX4{D{H{D(y4-9ZFwd@1BBx{iW4?@t?Njhkt0gsgXBbAyy(G zLYr=!XdP4uVT~rZOZ3~MR4F2W`GZ7@Bj8wIgdYSHdSOc1$?1Vg)tR7p0&cyBWqv|o U*6VygU9SMcyRX-9GGO8l5EOL`WQzE66TtyO1T~q{01u{YH(2aiY&)ZWg+BA* zqt9ZpC1Uj5KgdVoxt)xWm^SB}d(U^y{m$3h--q9S0+_)g4JnLpjB1GBf;1Ns7{etQ zUDj{~nFI`sb7VCnFd}y*;+T}_t8q+8pX0cu;X0-{ZZPzXnZ7T)z;Ydb!Sc;5TT~g? z21Bf1IaV;s5Y3FgU{H!~RWKx1Ek``5*S3WBT!JZ4GcAXqyA+s}H*4l@xXm#`BpKp` ziv6#RR&wiJMJ!pes3#D9@JeQ;cFcFCjsc_@3>oKa)7j3I0?%@`<^D}+ZgJe!aR+yG z+(VwDpyNJfb@ZX1Veq(Y{%Dv*&vQKqdcY77wvIW>GpNhLwp|?$QDjK8IdClKSj5r^ z22ZzkL?xi=O~R^~&7xF+lV4epQ76|AejsWjlv^kKz-maxa&ymUgn$MSW-U*8+QQim zUWa!(`wftN?slx6L0IL?bC6cfEMTcIDJ0N4@@ucUt03W z6QGu~At-sQT+ybBz>uyA-||GYEhK%`piT+81sfQp%ax*w$c#ZLJw;JaccjUlqSX+2 zMqbS}!M;i$2Fb?4O;Q}E+t5EysTlZVXg}1)*{HEx&MJl|XH~;4XJgWE!z~{mvQEvS zt6`w1O(<*oP$wFQHNf`~-$TD#7}{ra9U!sZg!Zci=pr}S067VoOz91D?{$L0+Eh;i z$&PKwIuf#;MUrBbo)|Q6TE%H(IfI5_bkVP+V;VguP^Lt}Y@in=$@8A1`AEn!RBa%7 zh!V$Hj&t;mrK!hITZ5TU7oay~G|;;Tu6%(K{f784i6iM`GZhhiP6|96ayK%)14Q&n}mKmr$g#`EUAH{(D5ZteiAqV6M)iiek3O!-J*I)@xy*=WYYtPjr? zU;CKDyoV}bd{M-))JAoq_=Ac?t0UV4IwEA&Riw-YAziC~Avle0TN1|hR3tz3E?QC_ zSTGkZgo+3wO(VkdkK$|c%mxVA^|156;WxWI9m;KGJBmie<~TeR`dFBEXX2X(Fp4ok z!Nw~c5uL0wjaJbKi;Grhs|x`Fj09N35}`80Z9cl+(z>e&!BcJzZvwnU?HTju)|m_q zpNZec+K=+eYVBr?2!&15rXZIJ}OO%)0Yh()H zcjRy39rls^ZHZC|(I__o4t%(%GVM5LSul S?9r7aaghq%TkjKz*5rTZxpr0n literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_char_at/test_char_at.java b/regression/strings-smoke-tests/java_char_at/test_char_at.java new file mode 100644 index 00000000000..3b8663d62ae --- /dev/null +++ b/regression/strings-smoke-tests/java_char_at/test_char_at.java @@ -0,0 +1,7 @@ +public class test_char_at { + + public static void main(/*String[] argv*/) { + String s = new String("abc"); + assert(s.charAt(2)=='c'); + } +} diff --git a/regression/strings-smoke-tests/java_code_point/test.desc b/regression/strings-smoke-tests/java_code_point/test.desc new file mode 100644 index 00000000000..012c7c3501b --- /dev/null +++ b/regression/strings-smoke-tests/java_code_point/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_code_point.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_code_point/test_code_point.class b/regression/strings-smoke-tests/java_code_point/test_code_point.class new file mode 100644 index 0000000000000000000000000000000000000000..1d5d2269325d6c4baed8f6c6f44326db9fc57985 GIT binary patch literal 999 zcmZuw+fEZv6kVsCOFJE)43|~`0Yz-7f+BbW2~ag@sF$QhBQIo_9&n({G&55ZUya5G zqaVPF#uuNxq$HB)yZ_)P@CU@W&q!NPU-rzbv-aA1?S1CQudm+#OkqxgfuR_N<4EG9 zhEo`cg2h!8r!^=T63D0sXGF-T$ZALkIDs*NPp=-qSeeMOe>-aZp z-(0QmG6P#?P-bn%4(1r5nd}1wDesm!Lr2ke_?_C;D);USG97H0w!_d?3QTMBwpk5f z73ZlsLu}Tn9LQ)Tx8_;=mMxOH1MUYa7D=vDUE2x9H_Rudjvn+f3=Z$Td$#xGWf-4_ z@ztUDLPr<6seq0Pm}E$c)QO7etWPX7tlacG*VAzklRAxUTE`_!Go)I~QsCLn`eMzl zlsOSE^x}tK2C!A%=buF18vvVrPbSXFWE(Mgw^g zXi@VOS~x>*nftcK%gvF|`hprA(6*N`O!v#6E60*)F>HFHdnUF+F-2bk^knpu$9BLz z3L?@Jl@Mfz<5-jWlTsse_Qr@TeL{2_J!4WGk|DoEVi(Gz9jMCVKkM3@B) zoAkSQ(D52=I8Lli$ouG1(U(f4_K{W5Pvn87)v3@v(Trpro!d~Q50Ijt5p7j#Oh~B7 Oi0JcTjwixq27d!;VcgOH literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_code_point/test_code_point.java b/regression/strings-smoke-tests/java_code_point/test_code_point.java new file mode 100644 index 00000000000..faf9a2051d5 --- /dev/null +++ b/regression/strings-smoke-tests/java_code_point/test_code_point.java @@ -0,0 +1,14 @@ +public class test_code_point +{ + public static void main(/*String[] argv*/) + { + String s = "!𐤇𐤄𐤋𐤋𐤅"; + assert(s.codePointAt(1) == 67847); + assert(s.codePointBefore(3) == 67847); + assert(s.codePointCount(1,5) >= 2); + assert(s.offsetByCodePoints(1,2) >= 3); + StringBuilder sb = new StringBuilder(); + sb.appendCodePoint(0x10907); + assert(s.charAt(1) == sb.charAt(0)); + } +} diff --git a/regression/strings-smoke-tests/java_compare/test.desc b/regression/strings-smoke-tests/java_compare/test.desc new file mode 100644 index 00000000000..38aa025f416 --- /dev/null +++ b/regression/strings-smoke-tests/java_compare/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_compare.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_compare/test_compare.class b/regression/strings-smoke-tests/java_compare/test_compare.class new file mode 100644 index 0000000000000000000000000000000000000000..3a807f4d203aecb2c12a4dab57637aeb3ded9359 GIT binary patch literal 623 zcmY*WO;6iE5Pjn~w&NH`%vTBxA1!SINaex}RJEcYA=37c2njCL##y1IiH+7ye+(Cn zoM|PHiqziuPgI?CA!)U%+1)oYZ{Ez_{r>S2z$O|#e9U^Nd3aKShdCefcB%mEjtS1TidFW8P-v_k66~F%D+v=#70Zu|@LS11M{-Y@jA|y+>~oa#&xDq*PsLXeU<~5~ zOLUCkXBh!g1bB`WLd}G1^hA8J@$OOVuGWbr1piXGcoE*OFyLUkD0g2fA12(5##(EJAb98+uS*C^T-DBr?4 zx`F%4a9BA<2%GOkF6i*$-)1QxBW2J%>MkaEGc+|Uu$dPHs-bs{(m7oF5_aJ`>=Eaq RF2hrV6}&a-r}L6Ce*kI)bz}el literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_compare/test_compare.java b/regression/strings-smoke-tests/java_compare/test_compare.java new file mode 100644 index 00000000000..c052ed429bd --- /dev/null +++ b/regression/strings-smoke-tests/java_compare/test_compare.java @@ -0,0 +1,9 @@ +public class test_compare +{ + public static void main(/*String[] argv*/) + { + String s1 = "ab"; + String s2 = "aa"; + assert(s1.compareTo(s2) == 1); + } +} diff --git a/regression/strings-smoke-tests/java_concat/test.desc b/regression/strings-smoke-tests/java_concat/test.desc new file mode 100644 index 00000000000..fb784efd723 --- /dev/null +++ b/regression/strings-smoke-tests/java_concat/test.desc @@ -0,0 +1,8 @@ +FUTURE +test_concat.class +--refine-strings +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 10.* SUCCESS$ +^\[.*assertion.2\].* line 11.* FAILURE$ +-- diff --git a/regression/strings-smoke-tests/java_concat/test_concat.class b/regression/strings-smoke-tests/java_concat/test_concat.class new file mode 100644 index 0000000000000000000000000000000000000000..e4143c157737bffffa1af323a7918a12ba9a88e1 GIT binary patch literal 798 zcmZuvT~E_s6n;+Eu3cAP42MHR1aWQ?m>N(KXzlg$}NALZ(`KO;B4wR}iLl zTwm<TqMg{z+g&?M!_0 zwirRJZr56TzcEb9#GCkdu#Ip7!TCX z$eo~AQVZdGq3I-Q~5>`oJmtnB2@n4o@wmRn6Ut|&$j%*^27rf0ZSCpXq z;((^(GVv!Bcz}WOi0wwY0We*(2ADX3u6~4?`GVXS?R-f&QG;SVlBbwU$z1sjB)pi= literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_concat/test_concat.java b/regression/strings-smoke-tests/java_concat/test_concat.java new file mode 100644 index 00000000000..b9909c723d4 --- /dev/null +++ b/regression/strings-smoke-tests/java_concat/test_concat.java @@ -0,0 +1,13 @@ +public class test_concat +{ + public static void main(/*String[] argv*/) + { + String s = new String("pi"); + int i = s.length(); + String t = new String("ppo"); + String u = s.concat(t); + char c = u.charAt(i); + assert(c == 'p'); + assert(c == 'o'); + } +} diff --git a/regression/strings-smoke-tests/java_contains/test.desc b/regression/strings-smoke-tests/java_contains/test.desc new file mode 100644 index 00000000000..2b96346d718 --- /dev/null +++ b/regression/strings-smoke-tests/java_contains/test.desc @@ -0,0 +1,8 @@ +FUTURE +test_contains.class +--refine-strings +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 8.* SUCCESS$ +^\[.*assertion.2\].* line 9.* FAILURE$ +-- diff --git a/regression/strings-smoke-tests/java_contains/test_contains.class b/regression/strings-smoke-tests/java_contains/test_contains.class new file mode 100644 index 0000000000000000000000000000000000000000..adf0ece000a23e9f4fd98803c8c74cbbf0aec72e GIT binary patch literal 716 zcmY*W!EVz)5Pf4OvEw)-aYzX*1qvli(n2r2H6W@07g9K+s?=W4+F2F1sSUQnkq^la za0aACq7vNssES#)Nr<$X-JLfx@6F8Lt6#qX?BJ<|B9;xTn7C&_!>WnrBm+|Wt&T##9O>Q z3;oKeI%Cf-p&dE;1ev!^w&&#bf4~@{+TOf?IY!|U`J)M}KR4d3MX#dJQi^3JVP05# z7h$j_6AdQpu&2gI3ECAJ29~Z*jo~{pEjy_`pyCuRV2@#Bz9FOkgfXu_Z9&z_LbG40 JM(Zj4-GA+{itGRY literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_contains/test_contains.java b/regression/strings-smoke-tests/java_contains/test_contains.java new file mode 100644 index 00000000000..5112c344c09 --- /dev/null +++ b/regression/strings-smoke-tests/java_contains/test_contains.java @@ -0,0 +1,11 @@ +public class test_contains +{ + public static void main(/*String[] argv*/) + { + String s = new String("Abc"); + String u = "bc"; + String t = "ab"; + assert(s.contains(u)); + assert(s.contains(t)); + } +} diff --git a/regression/strings-smoke-tests/java_delete/test.desc b/regression/strings-smoke-tests/java_delete/test.desc new file mode 100644 index 00000000000..27a1406cdb7 --- /dev/null +++ b/regression/strings-smoke-tests/java_delete/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_delete.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_delete/test_delete.class b/regression/strings-smoke-tests/java_delete/test_delete.class new file mode 100644 index 0000000000000000000000000000000000000000..f18891851b1e69aae1bc9416dd3316dab6c8e3b1 GIT binary patch literal 943 zcmZuv+iuf95IvjQ#*W+O+J-`aLV=_S4VRQ#0yHfkRZ0OV2-Na`9D7x{IB~HZBz`47 zz%xZkBr3r>{{&(-X_{Vm*|BHNoIP`Pe*gXP6F>!PD&n}raXE?w6#-n4$5nYOD!7L0 zDsCXJU>b!emQ)l`;<%|olRe8S%DBaGn<2HRd!BH8%jtN}EKhIQ!en6E43V1EvHT|t z!F=H@LulPG1;b3k>WG)!c1yT#B$x_q-RdyR=HEAV_0M|Q);l}prteyvovLh{YWlkI zaZ}$L;z=;a9foMlun+mwrqgu|@xqd9abI};2UFO>7t4}QLkekzxzpThUCTCwOY-V1 zLxS#VK*K{k;;3q<$w~rAhCtn*yEQxpO_iMx*2fM!cU^}VW5+abJk_v@ zIw_kpylU+V!#|N44a|_q|KEkkXe5SQeq*C>26H$~m5lM7F;_Z&7D$L=LYiMZU$n^s zr%Q4&BU;NTzb5y6q7izV8d5{$C({gkPl9ZEx`_DH)ot&T_|cHn0jU4ZyxhAZF=|43i8B z=8&at33aJ8NO9!=fvse4fKa0t3ilCySL`FQxes3IBf1Zzhjb~a_7UqLb^vW_fT>@S zIxwW3Cvv(ED#Zji<)WlQp^Z^-jw&&*Kd5lbbDXErg(Inzp(Y@aobF?$2Oj#0Q1CmH U3HMmGcd;12=iei~s-t literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_delete/test_delete.java b/regression/strings-smoke-tests/java_delete/test_delete.java new file mode 100644 index 00000000000..13bd09cd075 --- /dev/null +++ b/regression/strings-smoke-tests/java_delete/test_delete.java @@ -0,0 +1,10 @@ +public class test_delete +{ + public static void main(/*String[] argv*/) + { + StringBuilder s = new StringBuilder("Abc"); + s.delete(1,2); + String str = s.toString(); + assert(str.equals("Ac")); + } +} diff --git a/regression/strings-smoke-tests/java_delete_char_at/test.desc b/regression/strings-smoke-tests/java_delete_char_at/test.desc new file mode 100644 index 00000000000..94ba56a2c54 --- /dev/null +++ b/regression/strings-smoke-tests/java_delete_char_at/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_delete_char_at.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_delete_char_at/test_delete_char_at.class b/regression/strings-smoke-tests/java_delete_char_at/test_delete_char_at.class new file mode 100644 index 0000000000000000000000000000000000000000..cfd8561e5960688dd28ec9e722c7353b57d35ec8 GIT binary patch literal 867 zcmaJ*MY z8C=z{s^c22tGJ;fE#Va%Rn%0hF%(vL5C}iCJvVr42fXhHi-GMjB)4qW4j(YYD%Cd( z@omo%4B3wDikHKKzVKg5FeMJS?J{J#AvfQ@;Dabkl2qJe(6&tHm`3kjF9Of95wn;S&+(wfM%m~`k2A}x8M+}Ak)K+oFz+K#9$ju(U>hB9P{3kRKL&M>N zfpBS3>y^&z!6e(No(dhSZ!s8?p0}yxHc>BEo}Go(LT_5JSUC+OzNGjtZ4Bn4QVnc4*fO3zi6MUsxw|q0NOuO3UeZx0cBUdzYFNbJqp$pz%ZUDiQAzF;g*US&?OKL zd+gmsZGkyLYNJ~J)v(LWR#27u$}rMehWbi2?)1a@jd$-ka44(72yaLue( z_x$VP_MgYSAZP{zyRRUy=wQjx=4N)dMu(3^A^_Rn1ss?Mz~6WzTgUEIUDVXmLf@DBr7^d cwISkEV8K4z{bqS3qCAUGc(nlKcs)a zwVKcb65acwi1!W9rVEpocfapB_ujwfr@sMg;<1e~76oouxNXD0l7%}K?iNwPJ#8-w z+_zEGDGzL{;GsZ^P+#$qM8>HaM#&46c>X|!1UeuTx++rXGlJP(eMiXc3`0q%^i(9@ zjE;R7ztzbcIQCRTDECt@__XVN&fH9cV0DARWe>YQ9L0frrF4ax$|U_DqcHiZ(vMG$ zyf2=EDr$tP);9)Tbhyz^V-+28`)xl6b@&m%2$-AU2M(^G;-HOHLUUHKeKpC;I3C7K zX%0uA<6sTzb0~ZMkqlBoqurbJxq#l%Q(KzlduI8c6y8&1R=6|ZWfB%bnW$KXQ$DNhSmIrj7n z#=dJ#kbCXsdv0O(C&U=_&e{pAF-m7B?oVLx= z;+}l3G?kyqB>f~m4@B@UA9;WfY!zHDhgGcI;r`G)k-d~qsr`QtD{CydmoTo{tnGEuSY-?qZLNCyn? zP7krfPvh~!QL(BgU@r$|L6OfHzAdmNw)xc&=(|otiBBsF5(+5eA^SS@E0>yVcP?QZ zlyW1O?aa%ww_D2Z{eU$@d985)dx)t^I0qvX{*0rI=G~}PGBTxk)?#^X(_$qXbNu@> zS+~WJ3L`#@D>QA)j=u`SbGO}ZWNiX7CHDeTL)hjwn7N;@Cj2*(Xs$dA?~R_fn#n)9 E2H7QzvH$=8 literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_equal/test_equal.java b/regression/strings-smoke-tests/java_equal/test_equal.java new file mode 100644 index 00000000000..a3acb0ebda5 --- /dev/null +++ b/regression/strings-smoke-tests/java_equal/test_equal.java @@ -0,0 +1,11 @@ +public class test_equal +{ + public static void main(String[] argv) + { + String s = new String("pi"); + String t = new String("po"); + String u = "po"; + assert(s.equals(t)); + assert(t.equals(u)); + } +} diff --git a/regression/strings-smoke-tests/java_float/test.desc b/regression/strings-smoke-tests/java_float/test.desc new file mode 100644 index 00000000000..427d1fca836 --- /dev/null +++ b/regression/strings-smoke-tests/java_float/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_float.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_float/test_float.class b/regression/strings-smoke-tests/java_float/test_float.class new file mode 100644 index 0000000000000000000000000000000000000000..e4448d415584df7b1d4015eaf7189dcde13f9c81 GIT binary patch literal 965 zcmZuwZBNrs6n<{k?RKSOqpH2 z{(zsw1dJx?CqMY3#B)1gpr*~ax6ggfInO!g_UEt9UjfYEfsO%8s5|cf^-!9f?|_bT zIG@A?OzN0IK8Z9gYPh81G720;9etS4FsYetQ@SjOC9keamWk@wbtNHqgwH3h}*BG?< zrt>F;-tanpQ`Btfkq$)=zFc=aD=cqXZ!H5u$Z}jaa053vW(?fIZH_wz?xJeI#2|^N zTXhO*U>0)>BhsznSnfvU(UJTm-}ih<`q*8UNw*o2rQTle<>Z(*a1T^jrWfYv+NNlR zr=UjY+wKO*?XhZ7Gvx@qqr+^WR$T58x-cm`5xTJ*grZF)cpdW1cG0gjXRb(dJRyID&jV|oa z0Zn?9Zcv)87r-(jvh}o!fyoJx&C%C5t&G*}(0flhDHkAc4 zwrHwLlb;Z;Pm!5b^U}umkSOhg??Kx|b~J7#_o45i?+f}~9KiS%;X@@e^&dDps+#?$ zaVbZMpofzz4gF+?=tmhtDyp)I3|6StS5)UHv4;^mL=_1|Q8>oBFOVB1 q*E7d8%|vwq17><3nO$)8J=EAoXuaG=t&lO}P>hGNVP_+0C#+nD+1t&jn^YIG7T6 z;b9hY0`r8*qD&GMr@9viSJ zDQ4hI>WDDjOl5ewE6=mEK%L+=!tQ?#ui5Lzq57yzM0=y4 zf+gD~@O2D6llWM`BB5qVHoG!9+I;tD_d^`_VnT70Okl~!GFAxXVb9n0i3-z^R5Oir zbi^Kwjfc^A&QCnxux-1`yCGCND$%j(43v4&w9f!Hv@p;6^?2)4t{Kn#mjiDDMUExD z&G1Ql=GX5)-%KIO9GxslC}3hxdI^i0fkt3`4y>IZxBDIT6{_pE$Zzm>jj>;F4(=fS z41t%UfKjkAg=yAcS!Q(j5v=5*&ha(d4HzlGx<_50^6=Ieo*Y=&%IpCXfqRR>6@+~Q YJNEgj507B+?5dZ)H literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_hash_code/test_hash_code.java b/regression/strings-smoke-tests/java_hash_code/test_hash_code.java new file mode 100644 index 00000000000..d9f42b7ff9d --- /dev/null +++ b/regression/strings-smoke-tests/java_hash_code/test_hash_code.java @@ -0,0 +1,11 @@ +public class test_hash_code +{ + public static void main(/*String[] argv*/) + { + String s1 = "ab"; + String s2 = "ab"; + String s3 = "aa"; + assert(s1.hashCode() == s2.hashCode()); + assert(s1.hashCode() == s3.hashCode()); + } +} diff --git a/regression/strings-smoke-tests/java_index_of/test.desc b/regression/strings-smoke-tests/java_index_of/test.desc new file mode 100644 index 00000000000..f2fa825597d --- /dev/null +++ b/regression/strings-smoke-tests/java_index_of/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_index_of.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_index_of/test_index_of.class b/regression/strings-smoke-tests/java_index_of/test_index_of.class new file mode 100644 index 0000000000000000000000000000000000000000..1acb3335d57d4664c88fb229efaf15666076d900 GIT binary patch literal 631 zcmY*WOHbQC5dOxoy^b-Em=aRTD=oAEq;la_Kt<3>RZ} zXQ%`cNc7$xg&4af5%OwxJu}~9cK$xx-UC=g(}s-+3v~-GZA{`-85X7lrfry*5SXzs zi#dS?VQk(@Q<-Ecj?!(FdVW`i1nLmXH5I9BgHUQNekbT#aVQC+EfvX~-ia@hy}Xzc zC!UH3!|luqj=y<7i?G0Jg0&WO|8v;wxR(U-v&s=}Cev(RMWOt)A0NCw@=iSm!x&+y zO+O%Le!zGKZ!qs*2o9m1*Q|8C=x}B8$?m5li4)d+MkcV};4R(}Dg(%_eQ zDmo;H!o}_ZVZ7NIApWI4EPmmJ2hpuAzZIbt%2XvX>^tGkvmPh-p*m>rQ`Au zd@F%nVubfm{+s5L_%xPoK$m$TD!iLTkWfaoU)q7jU|`PGzPhE>((*O*^(z=>s7&eS z7`lV`;|AhS&Y~48H5hz17-jM&Sl;4Em*H~M0X<+=V2l^f1~2+LtA#dDb**cZ&mi;* Y=%wE<2E82|tP literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_index_of/test_index_of.java b/regression/strings-smoke-tests/java_index_of/test_index_of.java new file mode 100644 index 00000000000..270267196c5 --- /dev/null +++ b/regression/strings-smoke-tests/java_index_of/test_index_of.java @@ -0,0 +1,10 @@ +public class test_index_of +{ + public static void main(/*String[] argv*/) + { + String s = "Abc"; + String bc = "bc"; + int i = s.indexOf(bc); + assert(i == 1); + } +} diff --git a/regression/strings-smoke-tests/java_index_of_char/test.desc b/regression/strings-smoke-tests/java_index_of_char/test.desc new file mode 100644 index 00000000000..63382a455f3 --- /dev/null +++ b/regression/strings-smoke-tests/java_index_of_char/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_index_of_char.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_index_of_char/test_index_of_char.class b/regression/strings-smoke-tests/java_index_of_char/test_index_of_char.class new file mode 100644 index 0000000000000000000000000000000000000000..f87a10266837a4d7315b07e7dbb86aad5cd9ca03 GIT binary patch literal 614 zcmZWmO;6iE5Pg%_*kOZP&1R^$!B?%hXrN{9`a z#Cn_Uknuj|@Y;umK|;-@S35F3THSnZ_k%HsAyob+6L{le9&ZUjAGg~+R$=x}sF@iZ z9}z^}%I+b1S=?FLVUvB>R)^<9s75N)Mnye!cAIrM!NWP=Mg>nBprB^^krnVA(S2%sIkQ5A=k(K!x}>FxpdD%awtVinv4h62iHLQ~Uv^Py5`Q PrEyX4H>`!RTy^{pEv0g( literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_index_of_char/test_index_of_char.java b/regression/strings-smoke-tests/java_index_of_char/test_index_of_char.java new file mode 100644 index 00000000000..6a5d3d60bd6 --- /dev/null +++ b/regression/strings-smoke-tests/java_index_of_char/test_index_of_char.java @@ -0,0 +1,10 @@ +public class test_index_of_char +{ + public static void main(/*String[] argv*/) + { + String s = "Abc"; + char c = 'c'; + int i = s.indexOf(c); + assert(i == 2); + } +} diff --git a/regression/strings-smoke-tests/java_insert_char/test.desc b/regression/strings-smoke-tests/java_insert_char/test.desc new file mode 100644 index 00000000000..77d3ce2ebd9 --- /dev/null +++ b/regression/strings-smoke-tests/java_insert_char/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_insert_char.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_insert_char/test_insert_char.class b/regression/strings-smoke-tests/java_insert_char/test_insert_char.class new file mode 100644 index 0000000000000000000000000000000000000000..481304a9f6deb435deed6561f574cf664acb1da3 GIT binary patch literal 811 zcmZWnU2hUW6g{)R?y_tPrIg|aYPBj*1wX1UG)Bdm7*QWEn)am`b|>xB?XK>JKZZZx zvzkC+6MgqTX}kjkV*7G;_S`e)o_p{7{`=!6fK5EKu!xHWswOU3&~RCWD=MsIVdJWa zYZlgV-M|eCmSWztP($57gJF4{N0A6)8TipN8S%a+Tn4twpl?ZE#*Y|MwfZ}TbSH2H zL%u70@j5x`i}0-?Q{sqApJAaFbLYb={&5VG8v`2*=9c4~$XLA~2_5lVs!J=eh~hoz ztI~VU0S}vp{4=+)gd)SLI=4LT@3(q!DEX2=potT5UhB?z6R@r3qfeS) zsMcO|>Ss77EwpJQaWK^?)y@)$p^Hxm_o7p^CZ5`LT1|fLpySd07|O1QWGLKOyR?ls zp#&{&7i;tk7U`|9LPd>>PAM=oYl_SCSEVnbZ>BK<`>Kd2QPjsELl!GD>H%HVDAziM zwo^=vkbc=n7y3hF-ZzHOyWe08P}(S(Lu3cY9mCogA@@s(YGctdGIY++L)1ysz$#2M zsYIF39M~T;2{TY3_}r}O=GY0aRJ4a!7{Ew>K|1vv#$0!5R_SD**^gCA=f`C)`~&hw Br?3D3 literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_insert_char/test_insert_char.java b/regression/strings-smoke-tests/java_insert_char/test_insert_char.java new file mode 100644 index 00000000000..ac6beb4ffcf --- /dev/null +++ b/regression/strings-smoke-tests/java_insert_char/test_insert_char.java @@ -0,0 +1,10 @@ +public class test_insert_char +{ + public static void main(/*String[] argv*/) + { + StringBuilder sb = new StringBuilder("ac"); + sb.insert(1, 'b'); + String s = sb.toString(); + assert(s.equals("abc")); + } +} diff --git a/regression/strings-smoke-tests/java_insert_char_array/test.desc b/regression/strings-smoke-tests/java_insert_char_array/test.desc new file mode 100644 index 00000000000..d48c601b61b --- /dev/null +++ b/regression/strings-smoke-tests/java_insert_char_array/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_insert_char_array.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_insert_char_array/test_insert_char_array.class b/regression/strings-smoke-tests/java_insert_char_array/test_insert_char_array.class new file mode 100644 index 0000000000000000000000000000000000000000..3c0b53292301c003d9745154f7ecba9ccf1a4695 GIT binary patch literal 979 zcmZuwTTc^F5dKbYr(G5(ZMi4{qKLg9^@7(TmsU-Tpe7X!@IX#?PjGR&i@RGBeueM+ z0iVUBBx3a4A4QzgLM!6SoU`A2GxN=y+26ZGH!Rzf9z#f& ziZiFE%-lyd0*dN`JJ zEThbj?8d&T?MNda8Jm?ecv~gIV0NWTZi6K?#8|sshVkt4%}VYZ>7>6BO)YRwlV!5! ziNyFzPIb=@WSw5hZIGzJc3R6VzNVQ4ltzj=1*BV&&cY0QSCMRb!I=Em5Vrr1`gW_O z9Bo8@x2K9tYeO?LrEhuC?97suAZU<-c4h;Uw0%ihR+b!5k3qLENCq-w2kC2!PDW=m ze+c$f5ivwI)&dz4817I%Q)rlcl_P}KQ{h8IUPOOHR|?@|ZLJVV8f*DTp^50bd=s(N z1Mrz9;s;3VBQulIn&{a_&k^+XL-hVqg+i@D(^P`0L!**?;G`^$5yB=2nL-c!GdjxX zB@EH DG=!i}#;CO>ji?V8P5WYoWm2bZ7u{X_G5i6a z)dUio=)3<(;~gjv+m|~tXU?2^?!EK-?~k7V8hBu15f?3#lDK5Uz-1k-=&+W8gR4ng zv$2lr7H-(EHS?y8GAb6TgynS+hBAm$&kvufP;@-mCD1;>+)}=Z9ui{Z${Rv_yVsS3 zOiTIlW&fxngV&nO7e_+*goSn_+z&6r$1%)qENl>xTdsE^W4C+#z?ILGew2@77`;=z zPR&bHI~1RVgC*n$t9oDegnv+PM}hJWp7fR1l>xyJuIAiwa2quTb=+}~L6$v;#-_^& z9o)qxp*UA~Jgsgg2zo4$IhEMLJ%@XEpOBqDdeu3UZuB2CaY9%rx8}SF*wpPYC$$ht z<=x%N8O})wP3}n4n`-6DXNk-(<)^;z!c(~>o|+Y&OlIz2+vD*O3SAkhKz3)<@-U)4 zU-0bqvBtk(k-rLMi@IIBi-B~nIWF_5#4GWdsE$BiH4%A^<`^WTuri~*=cfkW)sJE9 zJW*y9L&}?SOerYa>*f51Eh~(?~RcDrA3XgXaNb{C-@(lENWpDNz^z+ zfzdSR4{D5AC^CF*mbEc<0xad6Ar=O(;$IMteTOyIoto7;2^h{JUDEk++6(^xKTD?D literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_insert_int/test_insert_int.java b/regression/strings-smoke-tests/java_insert_int/test_insert_int.java new file mode 100644 index 00000000000..b787141e51a --- /dev/null +++ b/regression/strings-smoke-tests/java_insert_int/test_insert_int.java @@ -0,0 +1,10 @@ +public class test_insert_int +{ + public static void main(/*String[] argv*/) + { + StringBuilder sb = new StringBuilder("ac"); + sb.insert(1, 42); + String s = sb.toString(); + assert(s.equals("a42c")); + } +} diff --git a/regression/strings-smoke-tests/java_insert_multiple/.test_insert.java.swp b/regression/strings-smoke-tests/java_insert_multiple/.test_insert.java.swp new file mode 100644 index 0000000000000000000000000000000000000000..5596a2c906d7e2a9c8e731f9ddba55e45b991bea GIT binary patch literal 12288 zcmeI&%Sr<=6b9hbx)QvgxNsN8MW@AfynzLATC${#p{Bqz5Ix+oKWuCczsmupLm${1sJH}`uN#jWDQAY;dg zjBNK$#pYEvQyD0&lDN8)oXNDhxU?|WH}TRYdV${xyi_(*scpKaO{(Ii_O@HeiQJLe zXzy5b#G#6{OwC~{i;QYV(la!ach+n|-{NRO00Q3&Wag+^A7+aS^WC52j5EzA#&^HZ z#|Q)<009U<00Izz00bcL?*vS{z^>?41NqH{^19Gh=S@@)fB*y_009U<00Izz00bZa z0SNp-0TD9xIKtS(C>@@@|G)qLf2Q^m#Vy4(MNHA4s8dW)Oj6i6uQd0C0tEsPfB*y_ z009U<00Izz00bcL+XOCbVVv6#+P*S(bxodTBGRrS{P&?R2ZK;LC<9snTkT0(t5OLEYI>i@@_gE?QS=3XMUst pu8lBMbrKcwmQbU}I;AbG)>^GPPz5iQsx(GLO&U=jFgEQ=Gt8VcQ-`6>#gE|! zd{z@kY@+Y}lg53ZKosN4-skMg+G}5a{QCM0z!qv6a=4&iO~pkG64r&dq~fyB8$w)3 zV-{CcT+?8psGy`l7a5xxuH%M+GQ<3a6^1;B+>ReUbwjJ=afg8&Fr;=|-;EwJB+TMl z2D#pGI77DK`utVgZt>ua2qs6{a(#xGW@Op#URoyuGqF-oVNiE$?+iw3cH+S1&s~wU z9PuzZbbV3!upN7md*bo(vGu{yF^@dMl6Y4<%Rj0#qrml#p2V)_@PI+G91(L<$1U6@ zsx9%jqtig{>X?H;jI5UJP%lP>)BwJ_~{lVdeitL%}^A_wj%sH_3e6I_7rt zhiS-*VZm%n;)ceWm{@Aq9>c1+TQ5$5_7Eb}UyAL#9^(bUnzET%g}7 zX+}C(>Vtg}fmkG&8W{$lq!*L`xMf?k?2EyQId0Z56QifY@~Wn_DVgdjn7DT zk>5159x`2IPNDDjG4ox3O9Su~f~ShmNE=YF0u^gis!Emuc`{%>QB|-!be$VB*cz|` h=8V}MvRx?hN63jUNKddw#05?glKx1vcYaWM^*86Xz$pL# literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_insert_multiple/test_insert_multiple.java b/regression/strings-smoke-tests/java_insert_multiple/test_insert_multiple.java new file mode 100644 index 00000000000..cce6881ca7d --- /dev/null +++ b/regression/strings-smoke-tests/java_insert_multiple/test_insert_multiple.java @@ -0,0 +1,11 @@ +public class test_insert_multiple +{ + public static void main(/*String[] argv*/) + { + StringBuilder sb = new StringBuilder("ad"); + sb.insert(1, 'c'); + sb.insert(1, "b"); + String s = sb.toString(); + assert(s.equals("abcd")); + } +} diff --git a/regression/strings-smoke-tests/java_insert_string/test.desc b/regression/strings-smoke-tests/java_insert_string/test.desc new file mode 100644 index 00000000000..b438d32d6d9 --- /dev/null +++ b/regression/strings-smoke-tests/java_insert_string/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_insert_string.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_insert_string/test_insert_string.class b/regression/strings-smoke-tests/java_insert_string/test_insert_string.class new file mode 100644 index 0000000000000000000000000000000000000000..39cc969a902e163ccfdfe821e6b8ae8b9f30aa07 GIT binary patch literal 841 zcmZuv+iuf95IyT$>^KfdoiquT0)+xe3JI5Rky0U`fP@I}5Cm#ps*SxWTU-ZhhmXk* z@C-Tej5 zn*&!cA1#VY&hPbjM*Cu14lfS>QN;U zVYDNCReC3k0_pEI_xLAn!A6nNDsFk)-);5cPLvgNQ;j{?uGvqpPKB{X>0j~rA?1k%TRVj zC;Mt7<)0sEqeSf(=_gA5sz z=hS!fRHIz$0NR$Fm>~JQk+f4|q~A8i(7Rt@j8Iy)Gh>(|WDk(tn!x(0M73D7j1O|Xx0PO J(&@PDnZGzkv2FkW literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_insert_string/test_insert_string.java b/regression/strings-smoke-tests/java_insert_string/test_insert_string.java new file mode 100644 index 00000000000..7c161205131 --- /dev/null +++ b/regression/strings-smoke-tests/java_insert_string/test_insert_string.java @@ -0,0 +1,10 @@ +public class test_insert_string +{ + public static void main(/*String[] argv*/) + { + StringBuilder sb = new StringBuilder("ad"); + sb.insert(1, "bc"); + String s = sb.toString(); + assert(s.equals("abcd")); + } +} diff --git a/regression/strings-smoke-tests/java_int_to_string/test.desc b/regression/strings-smoke-tests/java_int_to_string/test.desc new file mode 100644 index 00000000000..a615a10f538 --- /dev/null +++ b/regression/strings-smoke-tests/java_int_to_string/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_int.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_int_to_string/test_int.class b/regression/strings-smoke-tests/java_int_to_string/test_int.class new file mode 100644 index 0000000000000000000000000000000000000000..eff0e5a422e2df360086c15be326751bd69c8115 GIT binary patch literal 859 zcmY*X+iuf96r6P~n>bE$Yf1fGGfQwPYP>A4?ip#jd zv8*DDd=ytvRI!3<5nSiEp`wH`M};A?qPwneq+wg`W5dP+Vac@v{iCiSi4@084Xaqwuz&=EvR)?z4K>_i$a$=qsaw6;_9W{Q$FUubbq#fF za5OaB#vO{fTHhewi9W|&4fk-LAvx1{***{*IoE1Q$FO<~sTpg}lA4M%jRlcQsj0|Mw&_pwZuB~CYpC3D{3=`8?? zixkx~eHCbBw1z6jU|&5VGE~EUlOc-5DfKfHdVrmz_8rQzBLs$6tfYe@gocRyMELD7 z`0wOj0-HyOR7Z%8In}f}&+&W|-zQH_WKK0qQ8e#zKa$sk{z9hCAX6 zl|TZiz4u2I#sQL6w#J@$GjHC^pTBp%0IcFeh&;*x#zIu^IuC(yfr$`Vlm*^|n8aIw zcZA`pOjBj7ZYSxcPGzH|nglu^>5j8Asuk8W7tJt0_+ThAO}z1=af+Sab3XjN(tbz+rCJ|4?686m;|H5Ic-cHG@E!-fpyU1qm8vZ$oOUoB1+#~z_7P;S!$?GzW zGZ)iy+Z-Rk5(4JTV}|7nF)|8zV8<6I^)8144EGwZcEtcgC2@n`9KyeZpZN*D-{nQG QW6Z*fKD((#*zqv>2xe1s)c^nh literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_intern/test_intern.java b/regression/strings-smoke-tests/java_intern/test_intern.java new file mode 100644 index 00000000000..7f9d5283597 --- /dev/null +++ b/regression/strings-smoke-tests/java_intern/test_intern.java @@ -0,0 +1,11 @@ +public class test_intern +{ + public static void main(/*String[] argv*/) + { + String s1 = "abc"; + String s3 = "abc"; + String x = s1.intern(); + String y = s3.intern(); + assert(x == y); + } +} diff --git a/regression/strings-smoke-tests/java_last_index_of/test.desc b/regression/strings-smoke-tests/java_last_index_of/test.desc new file mode 100644 index 00000000000..77bc5b7f18f --- /dev/null +++ b/regression/strings-smoke-tests/java_last_index_of/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_last_index_of.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_last_index_of/test_last_index_of.class b/regression/strings-smoke-tests/java_last_index_of/test_last_index_of.class new file mode 100644 index 0000000000000000000000000000000000000000..4455da4d17990ad4ba7072f2330d39bebd49531c GIT binary patch literal 647 zcmZWmK~K~`6#ia!+v#=-EJb!#1px(JAb|@v(P&T;;wpzFChmny+kp%$t!cZ2-@?VC zXElLD6TSPRh;ORw#+XjtOuzZQ@4b2N*Y&p_0JhNa;GyNB?c%nFJGfhei#dUL4-Q%a z_dG0MQDBKMvn=ymWra?Y{DsbCI8ZTx`UGcNC%Sk_sB~7}5vn_BtO!$Gov63N(@FAfHhgHB>~evlq+9LqE5 zV*--|TZWMg36>1m#>WFJ`>4Ywv<+)>Ad{ob=QmZq%(65i1pj*qtoV3{M})>$w-+9( zsQ3r!6`4+s2z67@t|@5mkTBcnj#Ymsk5_lO0b_KB1v#M^t6XO)9+kwMD29B&jq78H zTkr8ysL?i$;8O+MElhHp;=g&`iFbSL3iR0!(ctKmAfblo5w#DC#lT` zpL~IRfySKk5%uqI-d{odG%i-@(uB=tn^g{fg44S^`5FR7eb6-)1ZH^gtZ-|TXRFK& hOb6~IY8MdIPpDSD!X6vnlxK`=SpGBfh}kl4^EYGRe8vC( literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_last_index_of/test_last_index_of.java b/regression/strings-smoke-tests/java_last_index_of/test_last_index_of.java new file mode 100644 index 00000000000..8b3a0904d5b --- /dev/null +++ b/regression/strings-smoke-tests/java_last_index_of/test_last_index_of.java @@ -0,0 +1,10 @@ +public class test_last_index_of +{ + public static void main(/*String[] argv*/) + { + String s = "abcab"; + String ab = "ab"; + int i = s.lastIndexOf(ab); + assert(i == 3); + } +} diff --git a/regression/strings-smoke-tests/java_last_index_of_char/test.desc b/regression/strings-smoke-tests/java_last_index_of_char/test.desc new file mode 100644 index 00000000000..3e9a3d4b547 --- /dev/null +++ b/regression/strings-smoke-tests/java_last_index_of_char/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_last_index_of_char.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_last_index_of_char/test_last_index_of_char.class b/regression/strings-smoke-tests/java_last_index_of_char/test_last_index_of_char.class new file mode 100644 index 0000000000000000000000000000000000000000..388717f4261b0458687f8c13e6e1a6735e6419c8 GIT binary patch literal 623 zcmZ`$&rcIU6#ibjyVGtLS&Eh_6#Rh(ILL)#V>GBqgFr}$30#`l-2n#5u9@8${}wJD zJ*x>Mn&{pCN#mOhwDDjjdGqG|_`dJG`Ss`94*(l@;-ijM4Rb!)xLb$7J%M>2E?NQ$ zJ~~(wSR%|W%RE=6&{>+l)VYj?Dk0Dz!RzW&7taXQmDRTdXERF_Vfu|u)z0WVQfA*4 zbK+d;lrYsVWPG+Q-<4s3`-ECI9$sVk{cL1n^;+AGg+k@UU?|z>G*KT0+0h_Ak>=^C zd@ln8m?F3`ie!szsv(6F+4R@Lqi&$iNA?eWl))=kdmgjS+*ZB#Or!P6HbPVll0S+U^l0~EHc zaQ3PoI~Utq{Oa&ce7kE`pwG4t(`>ymNZcBZOZQOW11vTxTWg`bM78?`&IQ7G?;{%D z;T~MU`)M&MB}Nkt`z{lDOf8tIh8d33LBG)vX!5sUb_~B!QUWtgaf#Xmg!2hb^(&kS T;*Bbc;-V5fx7u%)gm?Y|i7a^3 literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_last_index_of_char/test_last_index_of_char.java b/regression/strings-smoke-tests/java_last_index_of_char/test_last_index_of_char.java new file mode 100644 index 00000000000..029d59c9d68 --- /dev/null +++ b/regression/strings-smoke-tests/java_last_index_of_char/test_last_index_of_char.java @@ -0,0 +1,9 @@ +public class test_last_index_of_char +{ + public static void main(/*String[] argv*/) + { + String s = "abcab"; + int n = s.lastIndexOf('a'); + assert(n == 3); + } +} diff --git a/regression/strings-smoke-tests/java_length/test.desc b/regression/strings-smoke-tests/java_length/test.desc new file mode 100644 index 00000000000..913afbf13c7 --- /dev/null +++ b/regression/strings-smoke-tests/java_length/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_length.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_length/test_length.class b/regression/strings-smoke-tests/java_length/test_length.class new file mode 100644 index 0000000000000000000000000000000000000000..9273d09869b9f51a7d8c54ecac00703acfcf3186 GIT binary patch literal 630 zcmY*WOHUI~6#mY1I@3-E`#_*td6kE47qVezLnK8LW7S0s32ex8dQ)y0re@~WAH&9_ zYc-*XB(Uc{VK{dxEpE;|_dLGueCOQ${c{aq7j*|Ylx;lA;JE_>6>VN*k;Sr&6$iFX zt~yx5x{WGfe$$I%5h*zg;{zFc-9YpRbWE_CGL&kMkgC-W31(~96NG$QhT_xcyepzF zx|kE^o(u_d9p(9FAHA%8b3AA$;HJu7=D zkXFaGz`tdFiQjZ%4Em`HQDkc+LE`4pwDgc$4bE*`!8j_V#xOrLE|G5jf^~sH#rlri z73`xiGB+B?NPtQ(*-yh^$UGmriVWsCk_FwNYU3$i1q)M--Gmn?ma>;{E?}EKV5WY< Unjt=nrcu%`+&5alVnVod4-^}9hyVZp literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_length/test_length.java b/regression/strings-smoke-tests/java_length/test_length.java new file mode 100644 index 00000000000..4222414fa80 --- /dev/null +++ b/regression/strings-smoke-tests/java_length/test_length.java @@ -0,0 +1,9 @@ +public class test_length +{ + public static void main(/*String[] argv*/) + { + String s = new String("Abc"); + int l = s.length(); + assert(l == 3); + } +} diff --git a/regression/strings-smoke-tests/java_parseint/test.desc b/regression/strings-smoke-tests/java_parseint/test.desc new file mode 100644 index 00000000000..9cb70f5a957 --- /dev/null +++ b/regression/strings-smoke-tests/java_parseint/test.desc @@ -0,0 +1,8 @@ +FUTURE +test_parseint.class +--refine-strings +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 7.* SUCCESS$ +^\[.*assertion.2\].* line 8.* FAILURE$ +-- diff --git a/regression/strings-smoke-tests/java_parseint/test_parseint.class b/regression/strings-smoke-tests/java_parseint/test_parseint.class new file mode 100644 index 0000000000000000000000000000000000000000..e1ffe0c72107860cfe03ac1f697018740f58a884 GIT binary patch literal 727 zcmZ`%U279T6g_u0o84@-=F7%dTeY@o+KNRfC|HY96$+_7M185W>NHhy`3Mpnyw0 zE{E`KaxugeEcsX_)Rsk(NNv1Ob6d=bL!n|qz4@|rAl``efr$I-ZKGA(zh@g~+D3F=?}|}c&&&wHW_R!hJZulg zx+|Y33sp5TF|S5KCsM`criF`e1|>rIZ)k#Z>$Xi^^>Ho2bu=SHm?1Q>%7-VLJ=S`t znaL@5A1e`7v33glS?54@4PmzV?`0|(`c7klRu!X4bnNNen%~jOcx1}R) zb=lrMhO<|7C&;zdzQDWx5&0uj=F8Dr6p!KWO%Qya#@=Nyi|(Z8b$IN12zgG4KhhEc z+~HYgIm%z{r~Og0RO4uUN^~P-1XQYp&j^p;=iVddenLKjJt1vjJUGz_XbmxW3hJyprYdsx4{^ zY?mRjZaJ2}!4OPmUNeM>jhbK>FI$dy-mF)J`$~$*QRkM!Fjn!o`F@)pbj(D^pst&C zH-=VeG+k3Xwd9F}FFgOPD-LXKilu%2k?S~*6hmC@b2fMOauwgToIRr8Rg+h1Qm{%~ zlI=*x13Xl)rX!Da1&?%WU{%K?rh0mkY+{QcH3(SfmHEVV8!khDS1HyZ@gJIpM-2Kf zl!Ahe$0&{NJZ+Qxcr1tw!!8b;+j#g4gpj%nsM6nYa$5$fg-Z2!q?+efgc5Pj=7vEw+zaoQ3-3KaU04`?pEwL+i(7XloDklIUG+pFT%cFNk}$K(%i z2Bbuy65RPuAZFb*5mZ{u&d$7f^JezfpYJ~a?4W0%ikk**nYe91!>TfO%BbM3iF@j? zX5hYsvI0G@u#OD_n+%P0o~A-(;V4O;g(>$U5iqa=hSFY`gxO<;LaY6bLGOiK5?)lsc6ky9n3vCIBW(ZE?~QjX{ET6_HCS++i`Z2=FfKIH2(5m^PniPf;9vMQMViu4_zTPEa{Rd4C4$ zry|sHLKiyuMOZ}LfI%xau}qN)*l%NV=I4?yi Po+32+i5jJux4iKe)@YJ< literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_replace_char/test_replace_char.java b/regression/strings-smoke-tests/java_replace_char/test_replace_char.java new file mode 100644 index 00000000000..82a023924e2 --- /dev/null +++ b/regression/strings-smoke-tests/java_replace_char/test_replace_char.java @@ -0,0 +1,9 @@ +public class test_replace_char +{ + public static void main(/*String[] argv*/) + { + String s = new String("abcabd"); + String t = s.replace('b','m'); + assert(t.equals("amcamd")); + } +} diff --git a/regression/strings-smoke-tests/java_set_char_at/test.desc b/regression/strings-smoke-tests/java_set_char_at/test.desc new file mode 100644 index 00000000000..650e7712278 --- /dev/null +++ b/regression/strings-smoke-tests/java_set_char_at/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_set_char_at.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_set_char_at/test_set_char_at.class b/regression/strings-smoke-tests/java_set_char_at/test_set_char_at.class new file mode 100644 index 0000000000000000000000000000000000000000..6e843afbe2a4b7cfb6c15ccbbbc95c7bc11bcbd0 GIT binary patch literal 874 zcmZWnOK%cU6#gy@Gs7^*K%wBH+SXP9vG}M@h!IhfrmZfhCUirF;igWV4mvZ~|3XY$ zx>gfNB+N86dCJ6 zT#F)s>nifXT~JWe5Erl;8cMjSV1r>{&Gdcl1$Nip? zErV3=b~r;~$9DOv-cg%-dm@+|N2cvE#2bNWz27xIjLk%i*f6M7%Q;JxsI@KOE$g_2+YH(HkY_#H z>2OcS9o*GvLico}upofP1iX(247nMmHtG3==XE`*I8R5xLmiLs_#ZN_+lSl=hgMQMOYbp*LdaAmh78OH;tr2(Sb-=X!9E~a7w z=zYXSh&P8g_j_#46eEN)tS>XWC>BR*-Ucw~;V3i2cDl~-GkS9{^t$4Stw)k z877r7a1GZP@(b>RSznJmZ{QiYff~s_QJ3SUfm^uEU@n+1ItQXF|AMAM7_x=NB5w-b zRnv)6D~+HN8c1PRK`}X)u`-3?zcdEjmzF2}*S6gM&&z5J(*Xr**rf&*I>O< z>U*MwDAqngsFl(t2tO^E`k1I=L>r&MN63^@+8D7B5=V%)CeXhh!(${&{lf`3T_!mC z2de6ag8CcaB5|jKaVyKXsIw372kfUf4+D}wCRyp!Hm2heeJ6cxo%3d##_RAYnsVv&a$4ZM*1vBAZ1C3{E|nO>$!n4LL7ztqY>y$=7O_w-8O-L&M~2MSAmR+A zu88^j;ZeZl2OUhnkuPF~Vo&+umu>$zb(0JRyB+qgYB;^YP=@@i&>1zw6SbcxU#evP zn^2#hANpT?7iCl!%KE+D_v3^0o{}OyAcjs5MjBpbFggL5AarpHB^OPsFw|!$o$F@a zNI8&H?O!SjEf=d;yFs)Q9P&_+ux58wYQny$dv_*UKate`1kt=ov(&9V4V7Uo;)#$v znu?+ksUZP0(LF5EVv4jmR<7$_=w*Ubp+eT9-vZr??rdue_EQIA znuNVLg|X|IV`ScW*{+w{{sn7{H@%v|NGaxtgm~f5U4%uN zY&3|lO`aMdB^Z}zSeTof8o_s_S~gOBK*cMZz#YNL{6NP14Qp2ax&>V;3&VY-8?C4G GcmD#%SB#4Q literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_starts_with/test_starts_with.java b/regression/strings-smoke-tests/java_starts_with/test_starts_with.java new file mode 100644 index 00000000000..aba79d846c0 --- /dev/null +++ b/regression/strings-smoke-tests/java_starts_with/test_starts_with.java @@ -0,0 +1,11 @@ +public class test_starts_with +{ + public static void main(/*String[] argv*/) + { + String s = new String("Abcd"); + String pref = "Ab"; + String bad_pref = "bc"; + assert(s.startsWith(pref)); + assert(s.startsWith(bad_pref)); + } +} diff --git a/regression/strings-smoke-tests/java_string_builder_length/test.desc b/regression/strings-smoke-tests/java_string_builder_length/test.desc new file mode 100644 index 00000000000..ba9187109ed --- /dev/null +++ b/regression/strings-smoke-tests/java_string_builder_length/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_sb_length.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_string_builder_length/test_sb_length.class b/regression/strings-smoke-tests/java_string_builder_length/test_sb_length.class new file mode 100644 index 0000000000000000000000000000000000000000..cfc35874d26f44f91fc0291fbf4cc2eb1c058bfd GIT binary patch literal 722 zcmZuuO>fgc5Pjn~vEw*x;?OpH6zB&e4YaxR)(QayBt$8PAW(Cu*7hp6xK3m{{Fq)i zat5SCq7vNsO$agTwy_Xgc4lYiy?OKY=kIUd0c@jdp^9q;uA8`FLBq0%n=0Naqk`Ki zTQRU|p{$zLEUe>>fxCppx=0ckr@=5vo&Ra8mxTHK zAd&~;6IaHsRWm=Fh#(?Vd#Ui=zZ9da%t8p}t`}Z#SiRvm_T;lbAsVSn(xb#Z3S~4% z-)$X>55h(bb;6R$yP=2%-Ci08(ctko2z?o|3gLRHsYTFyX`_t|8*`Yq(ZM}JGY3Ap zTW4;eZ4_c#OhZERwTP|Go|++*pbgoXBgUOZQ@qqZ-J(MU$@%;x_Z{=rPSo$;7>|;9S2e!SB75=>{e=yaWYFW+-VBx6q>F{ltBXKNt zrl8NN5e+^|S&{g+ugqHe85C%rK|6E`Q|K=`PH}?L+b=Lq(dbNInjcX)L-}wD>xW{~ zGByXg8Uc%W>oCxQi3P5hpkHViSmbPJHfKAV4b+{=1okNm{S)-UR~R|rr94Gagl0cf KOEj~2SN{Od36Tu| literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_string_builder_length/test_sb_length.java b/regression/strings-smoke-tests/java_string_builder_length/test_sb_length.java new file mode 100644 index 00000000000..b616749ffb4 --- /dev/null +++ b/regression/strings-smoke-tests/java_string_builder_length/test_sb_length.java @@ -0,0 +1,9 @@ +public class test_sb_length +{ + public static void main(/*String[] argv*/) + { + StringBuilder x = new StringBuilder("abc"); + x.append("de"); + assert(x.length() == 5); + } +} diff --git a/regression/strings-smoke-tests/java_subsequence/test.desc b/regression/strings-smoke-tests/java_subsequence/test.desc new file mode 100644 index 00000000000..34585a7900d --- /dev/null +++ b/regression/strings-smoke-tests/java_subsequence/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_subsequence.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_subsequence/test_subsequence.class b/regression/strings-smoke-tests/java_subsequence/test_subsequence.class new file mode 100644 index 0000000000000000000000000000000000000000..0f8410939e1af315893c149dafa8190916146c35 GIT binary patch literal 789 zcmZuuO>fgc5PchetmC+?<0K`Ngs+y851^L{4wQ;00V!$6B&5& z)}DALEX-k^CU;z~Ctp$z3#+(JjVv_Kv`~P>P)(U@V-f7Gbxx!|2*XLpV4v;E(X!CS z4NA?b9=m(ei~oU!ap(uT42v^X_mv2T$Kn_YBz5+xHTwPL;Q!paq~D|34oy%S{brYT zc8WQsb<>=YjQmiJrUqzvaY6~&^$z`wK|csEyP8_2n*v%e=ILCZSDhlGsI`v3KBh$2 zbm|$%kVkP!J)}~Na>B`NwKU^1ltEkh0yT$wZ8eLVZ7qwp)lbk4P^{VBdlbGwe|7}^ z<1bdXduK7HqT2Eln99gyGFC|dX`{h9x!`cf%@SeD^twZSw#d;7a^n!I4COb08b^tv u%ow>Um5E=O8d%Rv0Y!(z=MTWu4^WjuXtRMQzSD*pa@PHHJByi~bAJGKN17A> literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_subsequence/test_subsequence.java b/regression/strings-smoke-tests/java_subsequence/test_subsequence.java new file mode 100644 index 00000000000..4d8d79cb381 --- /dev/null +++ b/regression/strings-smoke-tests/java_subsequence/test_subsequence.java @@ -0,0 +1,14 @@ +public class test_subsequence +{ + public static void main(/*String[] argv*/) + { + String abcdef = "AbcDef"; + CharSequence cde = abcdef.subSequence(2,5); + char c = cde.charAt(0); + char d = cde.charAt(1); + char e = cde.charAt(2); + assert(c == 'c'); + assert(d == 'D'); + assert(e == 'e'); + } +} diff --git a/regression/strings-smoke-tests/java_substring/test.desc b/regression/strings-smoke-tests/java_substring/test.desc new file mode 100644 index 00000000000..8a29460f529 --- /dev/null +++ b/regression/strings-smoke-tests/java_substring/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_substring.class +--refine-strings +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings-smoke-tests/java_substring/test_substring.class b/regression/strings-smoke-tests/java_substring/test_substring.class new file mode 100644 index 0000000000000000000000000000000000000000..3ba0b60e7f2f7faf54110943d367cc5063d9aaf7 GIT binary patch literal 740 zcmZ8eO>fgs5S$m=vE#a_^U*Xw0~AWhheU-`aiLU1Ns%G~9D$3LLChO zdtUR*J(OO20UD&^1#&Yf0+o8N*XYm7&N%m}%zN#GZ8lKry+((Nm~%Q~?vSM;8Tp|c z&D3!t@stTJaELWNfyws~b~W+CKLy+x@{CKo)p!b?TJsd*Q$mEzm`y=yL}5n#$Wo2D z{bJ^EQ!`GW^jpda)CVn7z(i8Om>hnvN1bA?T-6CciwBzLnYm3PsA! d9Ya??Kvlj#n-4s9oHW#su^uLSSx)s-{s3YPjAQ@+ literal 0 HcmV?d00001 diff --git a/regression/strings-smoke-tests/java_substring/test_substring.java b/regression/strings-smoke-tests/java_substring/test_substring.java new file mode 100644 index 00000000000..03a33fdbebd --- /dev/null +++ b/regression/strings-smoke-tests/java_substring/test_substring.java @@ -0,0 +1,14 @@ +public class test_substring +{ + public static void main(/*String[] argv*/) + { + String abcdef = "AbcDef"; + String cde = abcdef.substring(2,5); + char c = cde.charAt(0); + char d = cde.charAt(1); + char e = cde.charAt(2); + assert(c == 'c'); + assert(d == 'D'); + assert(e == 'e'); + } +} diff --git a/regression/strings-smoke-tests/java_trim/test.desc b/regression/strings-smoke-tests/java_trim/test.desc new file mode 100644 index 00000000000..c7a307c37ed --- /dev/null +++ b/regression/strings-smoke-tests/java_trim/test.desc @@ -0,0 +1,8 @@ +FUTURE +test_trim.class +--refine-strings +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 6.* SUCCESS$ +^\[.*assertion.2\].* line 7.* FAILURE$ +-- diff --git a/regression/strings-smoke-tests/java_trim/test_trim.class b/regression/strings-smoke-tests/java_trim/test_trim.class new file mode 100644 index 0000000000000000000000000000000000000000..33b34714ae2a5b39608f6624183a4d26028930b0 GIT binary patch literal 641 zcmY*W(M}UV6g_u$yVEX9Tb2UVinf5#@*tYOVgY&q5!wD6&nx zUiUErpWpge#hQ<&ct)ri&So!+k2c@lMcqx3K|&}@gap=oG!4BxrGM%i%dY+pYO`y6 z#G#Elq0(&aP5FN>UlD{#cl)RMTh=>|qBP~~^mtx`#Ym%%$h5f(PaaK^}uF!KxU zmrIE23=bH;4;oo3lMUb)FV5hi27woxE?}ep>jpJ}`3eJ-iQ`u02h0WeF$yCH=Q|wx V0`^q#E~rt-!Sdgjb`~+`K5Ph@2&a!L*Aq4OvYBVYz322O7NLgx(C!z-|t;Ev+BTn2bxF7x){(xt- z3aU(%-u+Kn_K*eK?%1$3@~({%${ZDj#Z?gm(hpVN3!bY$v|ZU{VEYW_mhx2im?2gwzhQ`P_q&oI z-Bg}@86CEz|5}47a43|=kT1P!9*EDP?h3D0Z-u_{dJUa8*9t}F#b6*k8r%9sfO9z~ z4K!#7VSmbA;tE5GAWuSc7J#CrhA4U|QJ?>+L ze#AU|8{VhL zW5k-(YmarE7fQuk?v3QW_ToOSkPt-bfJ-`{=!n8%8WBt|(dsR&_In#5!RgB|W z96gwb;kt?}avYN?5;9;)#WZF(W*G*?b=}Z?5-Lx5cO1@ruyRJ9eFh`zvam+Eq7HihOOlrvq+?se| z%DA*IJbznnHid0$*WT#v?5_S^*U*mvhGF@gw{&|aU-Dhk-dPPy%Mh-H8@Q?A7Unr_ zYq*2E919xm;l73x`ly;=*6UR(5L8=30gDWoZmx$%S|7Wv<1(a9bKrQOVF}B0)s1>y z-4!*TA+%LIfp?fur#d1SMzUMQ+*&vA1oZ-u^PQuZ!R%Q_^7yZ6>4WEs2DRS_sCK%O z)^zeOs2x6~5qg6H2HMq5!VJ7Aoh%wlI(vpsL5?#j-UYhlopR_XE#zqY$*zo|MLWVU zWC+i6g>l?Onz$d(1ue)X#%R@&w3aNDk&~dWFqj-B*+Dvu(3{aaGI;>@Svn$3HrfUm z;ut!1{R)MCK%IY&RKh8vTv1YHxe`g$%atgZXC1sMaZBQX#6@}S5TVKe!t2wMEhtm; ze?8qoWMd!EnHKmyVtW{z>5sRdenjFB33AqcN-m)`mkDA)1d$nIw%~O_H&NoJi#$sIF>QrmIn0o_q5Qv2d;dA68?f%x8jj{nK6Qp Nwjz6Ukq#k@`~_x<)`b87 literal 0 HcmV?d00001 diff --git a/regression/strings/java_append_char/test_append_char.java b/regression/strings/java_append_char/test_append_char.java new file mode 100644 index 00000000000..90e9ab089a2 --- /dev/null +++ b/regression/strings/java_append_char/test_append_char.java @@ -0,0 +1,17 @@ +public class test_append_char +{ + public static void main(/*String[] args*/) + { + char[] diff = {'d', 'i', 'f', 'f'}; + char[] blue = {'b', 'l', 'u', 'e'}; + + StringBuilder buffer = new StringBuilder(); + + buffer.append(diff) + .append(blue); + + String tmp=buffer.toString(); + System.out.println(tmp); + assert(!tmp.equals("diffblue")); + } +} diff --git a/regression/strings/java_append_int/test.desc b/regression/strings/java_append_int/test.desc new file mode 100644 index 00000000000..d65eecf13f5 --- /dev/null +++ b/regression/strings/java_append_int/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_append_int.class +--refine-strings +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 9.* FAILURE$ +-- diff --git a/regression/strings/java_append_int/test_append_int.class b/regression/strings/java_append_int/test_append_int.class new file mode 100644 index 0000000000000000000000000000000000000000..d9ee5046e7d68f976c15ed958ecd8f1ee7d75712 GIT binary patch literal 842 zcmaJ#j z4c`_7v+a0ddvMql!7EwJi9^fr2)RyV_1pk}rM(_B8peLR=vZ)w} zFxs>Fec{=Aju)*SSnn+Z1xyp>WZ<~A2w0YFU1Fpo^rF8)BN;rBkzm3~r9EjF zWn0yAp;O&0!b0Ww|I%9Ik12|k^MwqM7Vid@8xm&zWFARvRe4+HM9+rHD<#a@B6I>_ zpACT*6b(4R``pDM{|uA=5amm9hI~qZ{GR4&?i}l8Mf&-NXTIJtkmb9 zrf_cU1j?IZBwo}C$stlZHFb#ePHhOa{TbR3ipzz}5c&sXPmtw8>vdID(q|h-Bgmv2N76g`uq8OL#!Cf(Rm2qkHohNY|tr3>&vTabc4^rdp*Y31VB!3z>!!882< zo+(l)Q3>ApDBzAmnx>WQJDxjd&OLYe{pZI|0E<{tF^YnMX$4m~uBnKjAWc!4>j})@ zhKdr(31l#NCw1mOHwix1d(>DDj zhG?n$h9S1*7=j_QZrWlqXg7uXT7v1It(!JOs^ROc_ZxaAbQ3q};<&@0)LYhnCbi)N zZc98j<-JK?c>cED=?L4{cA9&l~bRJLA543*OQ=?k^;3D-~_HB#z3eU7oxSs)=!2xxrre9@-f zIDyYF-lH|0>MN>^Pc%Yr(}jE}VA##TI}&73&&E$m>;?42+wqdaa>Uv2S1<#nw~98(;SY{zFW{8`@lAJg_3er$XR+8eSNK_g{5?(_V=Lkh&|I#MLaXx%6 ua9kv}Lco3=i=kj(G?(cjyAK}widghJ)Ir34PLgp15p7v!ewj8AT=@rV@YR?A literal 0 HcmV?d00001 diff --git a/regression/strings/java_append_object/test_append_object.java b/regression/strings/java_append_object/test_append_object.java new file mode 100644 index 00000000000..e139a01679a --- /dev/null +++ b/regression/strings/java_append_object/test_append_object.java @@ -0,0 +1,17 @@ +public class test_append_object +{ + public static void main(/*String[] args*/) + { + Object diff = "diff"; + Object blue = "blue"; + + StringBuilder buffer = new StringBuilder(); + + buffer.append(diff) + .append(blue); + + String tmp=buffer.toString(); + System.out.println(tmp); + assert(!tmp.equals("diffblue")); + } +} diff --git a/regression/strings/java_append_string/test.desc b/regression/strings/java_append_string/test.desc new file mode 100644 index 00000000000..7b6ea8ccae7 --- /dev/null +++ b/regression/strings/java_append_string/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_append_string.class +--refine-strings +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 12.* FAILURE$ +-- diff --git a/regression/strings/java_append_string/test_append_string.class b/regression/strings/java_append_string/test_append_string.class new file mode 100644 index 0000000000000000000000000000000000000000..f2cb5cf8bea64858805fef9f4a7b85663a237736 GIT binary patch literal 1032 zcmZ`%YfsZq7=F%f?Meru444;G5OFYIiYO|G+zkq9GNXYnq^xJ;VAsyJGx3j@$RF^t zm~4q8`rRKzd{4(%Ci>O#pr zE299GN#|l;%vh8xqtx>Fd zp6f9f7g;J;)3J_?4vw$(4|yqI=+AAni#3VQ%h@HGjWSIAE8s%TSwHg~7{yP1z$>&3 zwrr8CA#mx#O^o97HW(K7ygKXMT2g4@qkf9p5twCpU;};lF3$v|8tnFx&xNnAM({YtBn zUE8Ej)}bFGb%e~M(OpN+7j&Hs}a7Bd1)Xd1>N=N(y z#z@+PgrUU1pCr~kf@J60-+F!DS~u2nc;)5o{t+lLZIh(aq|2h)#^9%hjE0^Fae6KK zbda^^xA>*$ZxbAK4Z;Rr^Yko0Bqav~Aop^

fY~HnML@r4WxVBGHxl=b!$VK{U8rN9v6#k~S-EOzEw58w$5kzgd)f);Hk+Oxvq##Mv1pHyP+ex$7cI)m|;}hsB zzzg_WOiCh&{`VDp7vh;+p@JlvnKNg;^UZfI`|J4o4*>VEt{{zZ2@^7ICUj4CzVTak%Z8R@*6?j$Ui> zIs@Bbh%A|H(_Ll==JKx?LYh_Q42g=_=9}GCjoU8-m@Znn*=ES*URQSY_j;kJw;P43 zYn$yxQ3S@Tu5P^D&^sQUv@^&{M)NPZQnk9a!PiYeHQ;i`ePiejpA%FnvKVGao~I>k zrJAAD*9739ibq(Gu&ClOiV~JoJQ2=iEU3s}h`@TyFzQ^zQ>-wI^w~-$nXlQlWee6- zO)IZ?hGCQ`qJ&k3=&33Rnu;)9q_4b~ zr)DR8z_Ui%vbnGH!h8st=oe6H((q90>)bJIUO%lTb=>XJ1x?Nl#%UbWG`%c2BKkpA z5EO%9T1V(KN;{)HJaq{6RRD2`)`;h%>f;pvik(o&;J;e4AJA%4>i1<(6J)0W1$UU7(^pHG{9`#A~knzLz`fNgN zz*9Q~h3qh`5hNf{dQnoXU;;5L(*L)GI2sthC%U~#$U%gTu_$5G|FYRJ$hdY|lX)+B jAeF{o52<}fp)UvpzaiRx@}xk5E{s5YMU-*OQ*`|gWS!(_ diff --git a/regression/strings/java_case/test_case.java b/regression/strings/java_case/test_case.java index ce3a51814c8..309abfc07b9 100644 --- a/regression/strings/java_case/test_case.java +++ b/regression/strings/java_case/test_case.java @@ -1,16 +1,12 @@ -public class test_case { - - public static void main(String[] argv) { - - String s = new String("AbcCdE"); - String l = s.toLowerCase(); - System.out.println(l); - - String u = s.toUpperCase(); - System.out.println(u); - assert(l.equals("abccde")); - assert(u.equals("ABCCDE")); - assert(s.equalsIgnoreCase("ABccDe")); - assert(!l.equals("abccde") || !u.equals("ABCCDE")); - } +public class test_case +{ + public static void main(/*String[] argv*/) + { + String s = new String("Ab"); + String l = s.toLowerCase(); + String u = s.toUpperCase(); + assert(!l.equals("ab") || + !u.equals("AB") || + !s.equalsIgnoreCase("aB")); + } } diff --git a/regression/strings/java_char_array/test.desc b/regression/strings/java_char_array/test.desc index 8282b808b84..62cc45997ba 100644 --- a/regression/strings/java_char_array/test.desc +++ b/regression/strings/java_char_array/test.desc @@ -1,9 +1,7 @@ FUTURE test_char_array.class ---string-refine +--refine-strings ^EXIT=10$ ^SIGNAL=0$ -^\[assertion.1\] assertion at file test_char_array.java line 11: SUCCESS$ -^\[assertion.2\] assertion at file test_char_array.java line 12: SUCCESS$ -^\[assertion.3\] assertion at file test_char_array.java line 13: FAILURE$ +^\[.*assertion.1\].* line 9.* FAILURE$ -- diff --git a/regression/strings/java_char_array/test_char_array.class b/regression/strings/java_char_array/test_char_array.class index 836942da1346e6bee0164979a451b7eec1a18c9b..38a7ecf41eddf662574382383851643fa631b055 100644 GIT binary patch delta 310 zcmXwzy-osA5QV?HuzO)yby-n<1QGEUOh|M~HTGyMv@x-{5MqMFSP&WupMlUAD+*sg zVldGJd*8@L915p6GiPQ_^1V4PcKH4KF#$sMTwF3SvMxDRW|EH+qo7%JamZ+jE^CxD z>;15vn!D(l=Ixoezch_bOHzg{I~;fv;k6l@~WV`x0lfH?ay1#(HEredO+MNLX6NXy3({}7?T%qkfSrdBC6 Pi`ZD+iIV-Y7>o2D@ft1Q delta 474 zcmZvY&rTXq6vlsdhM5ZkSR5ED#XpF)D$r8vlo;DY6IVv43yq0kH4ROw}s8!C_Ep1p7OswdTRc{hfEy8;bZ^GpK*624B{L zt;V+Ig=SJSrI~KE-$y57IO-kcw1~gBV+!Um8;vE!Sce1w 'z' ); - } +public class test_char_array +{ + public static void main(/*String[] argv*/) + { + String s = "abc"; + char [] str = s.toCharArray(); + char c = str[2]; + char a = s.charAt(0); + assert(str.length != 3 || + a != 'a' || + c != 'c'); + } } diff --git a/regression/strings/java_char_array_init/test.desc b/regression/strings/java_char_array_init/test.desc index fe5ffae7238..24437881467 100644 --- a/regression/strings/java_char_array_init/test.desc +++ b/regression/strings/java_char_array_init/test.desc @@ -1,11 +1,7 @@ FUTURE test_init.class ---string-refine +--refine-strings ^EXIT=10$ ^SIGNAL=0$ -^\[assertion.1\] assertion at file test_init.java line 16: SUCCESS$ -^\[assertion.2\] assertion at file test_init.java line 17: SUCCESS$ -^\[assertion.3\] assertion at file test_init.java line 18: SUCCESS$ -^\[assertion.4\] assertion at file test_init.java line 20: SUCCESS$ -^\[assertion.5\] assertion at file test_init.java line 21: FAILURE$ +^\[.*assertion.1\].* line 14.* FAILURE$ -- diff --git a/regression/strings/java_char_array_init/test_init.class b/regression/strings/java_char_array_init/test_init.class index be3baee56bd4f0a276d7b18454f832685f146dce..ff9c64510dad8e9bdd4cffcca053a0ed768259a6 100644 GIT binary patch delta 528 zcmYL_OK;Oa6otR>BNIDzaNPjq5nd&wbpnAB3KBvBiAAdtu?SgIMWO~-Az&p4EVlfH z;#Iq12U|c&fFjti;ur91DrPKEq|rHdM(3V;?tFEAmDYamfBOM+xZ!e$y5y9L!D$U= z9DL5|>Rg$5&F9NBG%rXlxKy-!(PfE9(%jx!ulc*=_%6-U*o% z1kd8vaXXDigLW@_IUEfYaT0H&)7nj!ZEn_~vWi;{+#_}6qZ3H5i)Ap(|5o+43!kW6( z6${07G(~*WLJlh|6^{akBL~ti*s2*G2JUxzJu-vUeq;qnKeB_gAC)x7VBFus*idHX zy`r#g+Ec9VC+uAoniEQa`;K}mloQH3)S96)!QG*pwVA HOg{M+MhHx` literal 1209 zcmZuxOH&g;5dJ2~W|C!rB_TXiPy{6qAPS=LP{9C#@~{e{1stp;jJUYT!tRDD|A9xZ zaPg>Du_{<%>D{CL9gDJO!&@q;?w;;%db+>v+F$$MegNphtcqH+ama{6Zx@}Mm@s9wDo?oHOBv~r*)-In zfk8i;S^5X17~&Y#a1Zx69%vZBsD_8gNNY?(0(A_^q_8Yo!#E}w8jcf<9`-%%IJUzO z5SE5VnA9+Z$8@x8hUif>98WY%W9C#XbIWTY=Mi=(L+>P)GO}MzdTL5qC#!zzdLmC; z+C{=A%1oJd`YF-m5m~~>5799E>Q1{U;kpD_#Bm~dKE+{66jr_0{-~yCB1!*w)%6U= zb6=P;a_&_*WwB8-EcXnc+}KbD0r;k26~){u;;!7-|0U2?9MhVyXrX8wR)lLhV&#Zs z+5)dg0otZTw9uZ`(qc2cK@N$mAebCA$woRgk!GZo&Rww25{L^V!@iTof{VCBHbL1W z6#4;wboIM3oeJuc*;Ggu*_5JN*;H5xuG`r?1Qt@e2+sIMNZCbbb_YsV3E{HhB}8@* z-9~L!Of8{e8x?!d7Isnj^T1sK*VPYa-QBUO5~@$2Q(@&R^udsSE72H=)trv|{&xQn zy4GC2zlB5O*6{1Zv2ZjfSCuqZ$$7FG>WcXhsEn2{iPg3Ii0$K*u8CH;ChR zh~qsWKM~8niRUKDQV(SxiyX}ym+4gyeBYKyW^6i?BbGe zS!QK;Ac|S9d*!t{$Lg}BJjtrd8tcPbu{+!_wr^rO5{Ohj@MvWsG-5*6l%5K@3*GIC zk9Z6gN$VO3AB9ez`CB~+Hb4?Vq>^_LHMcg*z^wq)HCA% literal 951 zcmZuvT~pIQ6g}IfO-NIkwtTc&v><5OTJQ_MTIHkS$V|nDIy%J%CbT;k3=JfyKZX~4 z^I4r~XJiJSeDOyy-YorZ;5kp=mAddfN0n?)sL~@t#?pxoPt@16yZ^R;`ZZ zKV=9Tg*OaR&1rLnMBVD}weHR)cV7!IC3Z}!!!TyNt8beh%{klbY|S-%*XnFl#Km~S zH(MWGn!5u$X(pKrO0{L5@~aJ}>$doFORyzo71D66DR$SL{1M+e}{s0dt z_NO=*k2E|+y?7*j!uVIH`&iED&H<{2h&B7reiV-)LB`1Gy9byGG6VETDHZQw zcptGKEM$cSvS#VEgG8u^Kqrw|$jC#%3`I(mTY!cY#L=X#cL{Nc(8CBHV?oAcCL@;} rBlN^s_w$1`fm9la9`t?4(q~BFZ&1%`2382J2tx5iVc3;{q^rLH7FffW diff --git a/regression/strings/java_char_at/test_char_at.java b/regression/strings/java_char_at/test_char_at.java index 337c6524099..9ae02733fb8 100644 --- a/regression/strings/java_char_at/test_char_at.java +++ b/regression/strings/java_char_at/test_char_at.java @@ -1,17 +1,7 @@ public class test_char_at { - public static void main(String[] argv) { - String s = new String("Hello World!"); - char c = s.charAt(4); - StringBuilder sb = new StringBuilder(s); - sb.setCharAt(5,'-'); - s = sb.toString(); - - if(argv.length==1) - assert(c == 'o'); - else if(argv.length==2) - assert(c == 'p'); - else - assert(s.equals("Hello-World!")); - } + public static void main(/*String[] argv*/) { + String s = new String("abc"); + assert(s.charAt(2)!='c'); + } } diff --git a/regression/strings/java_code_point/test.desc b/regression/strings/java_code_point/test.desc index 35ca0cd6f4b..2b94f1fa0c0 100644 --- a/regression/strings/java_code_point/test.desc +++ b/regression/strings/java_code_point/test.desc @@ -1,11 +1,7 @@ FUTURE test_code_point.class ---string-refine -^EXIT=0$ +--refine-strings +^EXIT=10$ ^SIGNAL=0$ -^\[assertion.1\] assertion at file test_code_point.java line 5: SUCCESS$ -^\[assertion.2\] assertion at file test_code_point.java line 6: SUCCESS$ -^\[assertion.3\] assertion at file test_code_point.java line 7: SUCCESS$ -^\[assertion.4\] assertion at file test_code_point.java line 8: SUCCESS$ -^\[assertion.5\] assertion at file test_code_point.java line 11: SUCCESS$ +^\[.*assertion.1\].* line 8.* FAILURE$ -- diff --git a/regression/strings/java_code_point/test_code_point.class b/regression/strings/java_code_point/test_code_point.class index c257f0633ec65db2643a2b314c4f01928dc14660..f2f5fbad63a60c992bb2f3c9ef2d15fb99700de0 100644 GIT binary patch delta 482 zcmYL_%}*0S7{-6IU$fnA`B;fIh*%L7w`c_`il9LgPnDAv1D9sS#-OAn?Z(8DG5!T) zZzLoT51u@z$(lfdCodfRe>A>BVw}To-aPZn^S(3h{m**s_|L%+Q0IO?M8)TVW+K3* zVxtP$R2K^jF&S`)%LZ2rrVOqc#Ksb9ssRI3G}8gsxUQ*fuQf(WPts)l^>VWHG{Z!4YVSRXa8pRoTA$Pui0*=6c(k#q6i`sDOM=O5B$0V@qj{v16fK#5K;(kyb_~VNyy%~ zkZ|#$2Q^uvBzpIM;6EY8nTA9Xok@N(^UOQ%*L;+({l#CuzyAQLJPHWu^Xbpf&b5F6 zuG@%=lne%V^cgZ_q-11Raw8yXaF!86%4S!Vj0W7KBDuA{I6c}`TAFzgy^1QEQFE;_ z7w@b$*QSQ&1-ZF6s&C9j+fSpF&4y%5``iCEpHp;lK_3<4RFfy7m{&|tRn(YN+-5S# zi=O^F+*RCTN|28mFXQF<)@oyUduzQJOYSQk@GyBRO38_MmV6Ln$+-1q_Y#7FF7yOj zPuL5sna|hS&c= 2); - assert(s.offsetByCodePoints(1,2) >= 3); - StringBuilder sb = new StringBuilder(); - sb.appendCodePoint(0x10907); - assert(s.charAt(1) == sb.charAt(0)); - } +public class test_code_point +{ + public static void main(/*String[] argv*/) + { + String s = "!𐤇𐤄𐤋𐤋𐤅"; + StringBuilder sb = new StringBuilder(); + sb.appendCodePoint(0x10907); + assert(s.codePointAt(1) != 67847 || + s.codePointBefore(3) != 67847 || + s.codePointCount(1,5) < 2 || + s.offsetByCodePoints(1,2) < 3 || + s.charAt(1) != sb.charAt(0)); + } } diff --git a/regression/strings/java_compare/test.desc b/regression/strings/java_compare/test.desc index 517b208c3e4..e7444831e77 100644 --- a/regression/strings/java_compare/test.desc +++ b/regression/strings/java_compare/test.desc @@ -1,10 +1,7 @@ FUTURE test_compare.class ---string-refine +--refine-strings ^EXIT=10$ ^SIGNAL=0$ -^\[assertion.1\] assertion at file test_compare.java line 6: SUCCESS$ -^\[assertion.2\] assertion at file test_compare.java line 8: FAILURE$ -^\[assertion.3\] assertion at file test_compare.java line 11: SUCCESS$ -^\[assertion.4\] assertion at file test_compare.java line 12: FAILURE$ +^\[.*assertion.1\].* line 7.* FAILURE$ -- diff --git a/regression/strings/java_compare/test_compare.class b/regression/strings/java_compare/test_compare.class index 5616013c523bf345c4c9743a55ef57608353b3f9..67f18914ea60035f71b5a2b6d3fbf28050aa44c4 100644 GIT binary patch delta 399 zcmYL_J5K^p5QV?HEW69HsH~{?!1pT{H8Cc(T3CSEcLV9qVGXY_r&U+{z~yQW&}zg7%2x$-rZYWktH8ul06S*Uq*N z8jW($Jg?UdgPNgcJl7rO(h6K#|M$V7qpD{b6vKw8Z<~{K@tdk!0N62CHIebj1 zD^XFjB;*is6kl3#)HfNMQF+oz4HS0!s*v=ZF0l@_`G6UD!TcxvGZykhF}(fI{#ajg F{1*XBGvU54k$*G_MUsscg}ae@7y21zkCC58!HwHm^N|6#7rJ}T(wZgH3PF2 zbWF>`bpvx2=5fQo0z+ki$FYbKFAUaxpL*M4I4!wv9W}k47KdaM`u2sL{S*o zXkeMazQ|~xX`_WULpf`E-rE;$@>gmso*{p#WIJS-YW&CDGqSSBEr#eMOG1oi+`ydN3L93o7 zNh2IoXfI1YQ>#YNca)B!ZhnMzgvnNWgq(Ja!dK|8PGEdb)75rUy+wfXE(088YmBXo zV7BQ0r%3`tcM*_^lvL3?OxkOtAxG+T5^mxyEZie|FUZ;fRZUVw1==sv4NTEj`-vGD qsI+?S_)cmKa4N`;U>(8G-a}JALCY>Xvo8sAP>K)bkS?cMYJUJ&teKbq diff --git a/regression/strings/java_compare/test_compare.java b/regression/strings/java_compare/test_compare.java index 8c1d4b71a0c..0a535fd0bf3 100644 --- a/regression/strings/java_compare/test_compare.java +++ b/regression/strings/java_compare/test_compare.java @@ -1,18 +1,9 @@ -public class test_compare { - - public static void main(String[] argv) { - String s1 = "abc"; - String s2 = "aac"; - assert(s1.compareTo(s2) == 1); - - assert(s2.compareTo(argv[0]) != -1); - - String s3 = "abc"; - assert(s3.hashCode() == s1.hashCode()); - assert(s3.hashCode() == s2.hashCode()); - - /*String x = s1.intern(); - String y = s3.intern(); - assert(x == y);*/ - } +public class test_compare +{ + public static void main(/*String[] argv*/) + { + String s1 = "ab"; + String s2 = "aa"; + assert(s1.compareTo(s2) != 1); + } } diff --git a/regression/strings/java_concat/test.desc b/regression/strings/java_concat/test.desc index 8ef2898e0d7..fb784efd723 100644 --- a/regression/strings/java_concat/test.desc +++ b/regression/strings/java_concat/test.desc @@ -1,8 +1,8 @@ FUTURE test_concat.class ---string-refine +--refine-strings ^EXIT=10$ ^SIGNAL=0$ -^\[assertion.1\] assertion at file test_concat.java line 9: SUCCESS$ -^\[assertion.2\] assertion at file test_concat.java line 10: FAILURE$ +^\[.*assertion.1\].* line 10.* SUCCESS$ +^\[.*assertion.2\].* line 11.* FAILURE$ -- diff --git a/regression/strings/java_concat/test_concat.class b/regression/strings/java_concat/test_concat.class index a6d4008aa268b84833bf1df2c7b8519a5ef4090a..a69c05921f673cc68295af7dbb43ccd41e10f1a8 100644 GIT binary patch delta 373 zcmYL^yG{aO6okKBSaw-f1q2jP5WFJ@DzVW*6FS68w4q!GF+rjf#LoB(gw8^F1uY;E zqrDGc>7%G;O$>kX&txX&OwN3I9z4a5@0T~Az_!UaF`Ze1ITMw*0||q9hm#JZyjU#g zESi|k|#4Vkt0o*0yVxWxI85SDST->AW6B)-2MjE4W&%Yl{q7iw$z!xRQ_N zEjHOw@HgxmJJ+rK@=wCtR5~j;nN{%CFmO9E~WcudwY(20sZNZ^%jCcF4J uk=79z38Vgqq3KL1@*P4F45s-%w;*RbFA(e|UCEHMrJ-8;iuh3xDl@-B(>Emm delta 390 zcmYLEy-vbV7(Ms)=ay2G6s&-#;4g|;6k*ViIIw||SQo-n2q7YY#t>&;fpl{a7hk{u z5=nIT0UX_Z3H8<({gUrHIp_Poli%dh>*v!mfE)@cX0XVxq+nSEMZyb71uGt|dST56 z4eJaWDpap>Q$-3}4BNv}Suj#{w@Qp~z#7=i%M;r~M0C|F7$G*1BuH9>!)kde)91w)+m4DG1TwV0qM{b$C*9`C^zxx3K zWRBJpw5AIah?VphQt^k%oSvpLW3WRpD#pi93eqEdx6tRLpfiGh3bi(Y|K(5YkK7v? zvqb)&gjqg03Wfv}{-_T{uAaeb$_QH0hLH=gk&LGbch{(A{=_b`X~K;PxF`<-ia2mG`pGp0sjOq3jhEB delta 457 zcmY*VOG^S#7(I91&Wt&Z`N*=ghnbIDM4L!*8I)}dLRw8FQVkj+EpyvegcfdEwyr=S zq4xco7Hy^PPEiDx?{&{T=Y02G{*X)Wlb2Tj8(7!j$E=Du4GA3r<~1y6NcvzP#rs7S zOFDcUvaDkTX%(xztvxZ4IqvVUNYG#HIH#8t=jzZoaqGm>yDOG01R1Og=h`W{PP0+0 zcG~C727|dZ5-o}dm8 z%H@a91~A6()ke_Yex}{R|1sAPJdHT1fEabiWKkhgD$>xfO{x*P2|$?eAB%pUFkQud neQ$aO0Xqa^2y*~cdVnN8L;Vx*mWUFNv&j(rWxnf-XCVFs=fgcY diff --git a/regression/strings/java_contains/test_contains.java b/regression/strings/java_contains/test_contains.java index fce2ee63047..6f4c60a1a2e 100644 --- a/regression/strings/java_contains/test_contains.java +++ b/regression/strings/java_contains/test_contains.java @@ -1,10 +1,9 @@ -public class test_contains { - - public static void main(String[] argv) { - String s = new String("Hello World!"); - String u = "o W"; - String t = "W o"; - assert(s.contains(u)); - assert(s.contains(t)); - } +public class test_contains +{ + public static void main(/*String[] argv*/) + { + String s = new String("Abc"); + String u = "bc"; + assert(!s.contains(u)); + } } diff --git a/regression/strings/java_delete/test.desc b/regression/strings/java_delete/test.desc index c6c608c0955..ff41e78b3df 100644 --- a/regression/strings/java_delete/test.desc +++ b/regression/strings/java_delete/test.desc @@ -1,8 +1,7 @@ FUTURE test_delete.class ---string-refine +--refine-strings ^EXIT=10$ ^SIGNAL=0$ -^\[assertion.1\] assertion at file test_delete.java line 11: SUCCESS$ -^\[assertion.2\] assertion at file test_delete.java line 12: FAILURE$ +^\[.*assertion.1\].* line 8.* FAILURE$ -- diff --git a/regression/strings/java_delete/test_delete.class b/regression/strings/java_delete/test_delete.class index 6d30024f108aeca8a2d4587aec50ce79b2f35ddf..7036ce13c9036943ef66368d595e31b8ed88ca47 100644 GIT binary patch delta 431 zcmYL_J1<006otQY?%aFs+&P%J#``_qGsc^mM29FyP>u--3Wb{Az%7JIr$#c9kdP=< zYCph#P!Ri0f@ZCA_E~%FwaudY3TCl4$$<(&>KTv5=+jfKVX1C z!%#pFD~AI{7&YY2wwAMX>&KjD0*;~=c5T2{fL1%HNY{@WYDKc)E zVA9e+TA>%qBDG909qp-tH)AEtTy&vEq8Hs3eG0GXT=cHjPpu>bm2QnY<>a8mG8Al- zTbHmBcJo!#Z7d`!=+%mfBu#(PeQDM5HvWj-4xK8A<$S`e;BMwCcq@09E3$>quaLYX z^+>Q?CG~s~o9dcrGp?Ln`3FxD7@F~AucR=fP+t@cErwPpxBX3>ttEj>Xe-oRVG=ha WoO{f_?{C=H$3@$Pc%}B**p46foiwBX literal 1126 zcmaJ=T~8BH5IwhF+iowkwop((DI#tuP!;j3s6YWB0X3f{&;I%M^A~_Atf)vKt6*3~0NE(6$#X=8>oSbW za3cl{ITd5b$B@K$6cZ{YQBZJGMYpWJrQ$ZG6x?A*kLaE!T;FtTZ^88R4NDjdY@H!8 zW7?+wm?5a;UNMA9jv*KltEMfUHEJ8eeJR28p{AQQLq>bMx}|^83zlwg7RtVB+M7jL z*j4uR>W4MG-og`g1=9@CnX0wlUoATgwLMwa6)?s4451CEC%a?Ie7g2xa10qtCL)OQZ3^=PNt(%>U|l|OsFsF4kv26gUjlQ5ma z3%X&S+6cWy1?iR$$I}c-U4ksKNAFpilRF~fV?(#R6M(js#T?l%(NVZ$kypuShVV>R z7>74R2J;*AfsDG2ELlE9{|Za?%X_A$AgDVs6#M9HkWNNtcx)H!y9A=2Vx*NMSKuNp z(X)hprP3gsulEpmvy0$rJ{4*rT*)iRNE4Atp5By7zKQ7C4r1d?s5^*nqh~zDo9Nm` zd=K4Jm-u}&{iTzZ(*v#Pqcj%?A&M{(#H9}k5shIODsqTp7917&cP|r)Bk)(6d4M1p rs0nRUDU3kZtW@J_i^$M_f=T@R diff --git a/regression/strings/java_delete/test_delete.java b/regression/strings/java_delete/test_delete.java index c91b16c5b89..ea846cd215a 100644 --- a/regression/strings/java_delete/test_delete.java +++ b/regression/strings/java_delete/test_delete.java @@ -1,15 +1,10 @@ -public class test_delete { - - public static void main(String[] argv) { - StringBuilder s = new StringBuilder(); - s.append("Hello World!"); - s.delete(4,6); - s.deleteCharAt(1); - - String str = s.toString(); - System.out.println(str); - assert(str.equals("HllWorld!")); - assert(!str.equals("HllWorld!")); - - } +public class test_delete +{ + public static void main(/*String[] argv*/) + { + StringBuilder s = new StringBuilder("Abc"); + s.delete(1,2); + String str = s.toString(); + assert(!str.equals("Ac")); + } } diff --git a/regression/strings/java_delete_char_at/test.desc b/regression/strings/java_delete_char_at/test.desc new file mode 100644 index 00000000000..0314c606e56 --- /dev/null +++ b/regression/strings/java_delete_char_at/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_delete_char_at.class +--refine-strings +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 9.* FAILURE$ +-- diff --git a/regression/strings/java_delete_char_at/test_delete_char_at.class b/regression/strings/java_delete_char_at/test_delete_char_at.class new file mode 100644 index 0000000000000000000000000000000000000000..ed3148e2f7e60738b9863b1e47c0d50650b289cc GIT binary patch literal 867 zcmaJjF9Of95wn;S&+(eTK%m~`k1|RvpM+}93)K+oJz-`=N$ju(U80-l%{3|pOL&M?2 zp>SzZ>y_^8!6e(No(dhSZ!s8?o;%cXo2Zv7PyUD2LT_5JSUC+OzNC0J;!eOY|EG|N z@>Z4Bn4QV%IJ9eq1xp0BFRYWf(B{GsC1}w*SfMYIrO(B3B{^0)#lYlJ$QJ2VCeO$x zYKLH-BoOmtlTnZ%g@qHSM_*8(+~yIK*N2Ebt>xomB(`g0liRg1)b3|!2Pm%PQ)B2K zkUm11fW~*pt3TE`WfVq5Tj57yN a;~x=^eStRPo@$mn2`I*W+1a_M^zv`0>bRr; literal 0 HcmV?d00001 diff --git a/regression/strings/java_delete_char_at/test_delete_char_at.java b/regression/strings/java_delete_char_at/test_delete_char_at.java new file mode 100644 index 00000000000..5f2c995b56b --- /dev/null +++ b/regression/strings/java_delete_char_at/test_delete_char_at.java @@ -0,0 +1,11 @@ +public class test_delete_char_at +{ + public static void main(/*String[] argv*/) + { + StringBuilder s = new StringBuilder(); + s.append("Abc"); + s.deleteCharAt(1); + String str = s.toString(); + assert(!str.equals("Ac")); + } +} diff --git a/regression/strings/java_easychair/easychair.class b/regression/strings/java_easychair/easychair.class index e47900cc0b20ba70177dddd97c472c178867b054..e6c5f66c42df9f28db774c6eb3ab463dd03b134c 100644 GIT binary patch delta 108 zcmeC-?B?V+^>5cc1_lO`jU3mREm;}Z7}yyE88{fE7`Pb}8F(1f82A|U7z7wB7=##{ z7(^LD7{nOj7{nQ}7^E5M7-Sgg8RQsx85Ac=u$XX}Ffam5Vqg#ynjFre!OP>o2oz8P J3NSG!0|3Hx4oCn1 delta 109 zcmeC??BV1%^>5cc1_lP>jU3mREm;`Y7+4tufus}zCxapb7lRrD4}%^9AA<#h0D}{Q zFhdA~2tyo$C_@%dMID1QLp_5mLob8EWC<1%Zc_$Eph*l2Lc$D_!&o$Uc^w#mB1%9J HCI)2y$e#`} diff --git a/regression/strings/java_easychair/easychair.java b/regression/strings/java_easychair/easychair.java index 55ca2a31bb3..caed962fb46 100644 --- a/regression/strings/java_easychair/easychair.java +++ b/regression/strings/java_easychair/easychair.java @@ -1,34 +1,34 @@ -public class easychair { +public class easychair +{ + public static void main(String[] argv) + { + if(argv.length > 1) + { + String str = new String(argv[1]); + if(str.length() < 40) + { + // containing "/" and containing "EasyChair" + int lastSlash = str.lastIndexOf('/'); + if(lastSlash < 0) return ; - public static void main(String[] argv) { - if(argv.length > 1){ - String str = new String(argv[1]); - if(str.length() < 40){ - - // containing "/" and containing "EasyChair" - int lastSlash = str.lastIndexOf('/'); - if(lastSlash < 0) return ; - - String rest = str.substring(lastSlash + 1); - // warning: removed this because contains is not efficient at the moment - if(! rest.contains("EasyChair")) return ; - // (2) Check that str starts with "http://" - if(! str.startsWith("http://")) return ; - // (3) Take the string between "http://" and the last "/". - // if it starts with "www." strip the "www." off - String t = str.substring("http://".length(),lastSlash - "http://".length()); - if(t.startsWith("www.")) - t = t.substring("www.".length()); - - // - //(4) Check that after stripping we have either "live.com" - // or "google.com" - if(!t.equals("live.com") && !t.equals("google.com")) - return ; - // s survived all checks - assert(false); //return true; - } - } - } + String rest = str.substring(lastSlash + 1); + // warning: removed this because contains is not efficient at the moment + if(! rest.contains("EasyChair")) return ; + // (2) Check that str starts with "http://" + if(! str.startsWith("http://")) return ; + // (3) Take the string between "http://" and the last "/". + // if it starts with "www." strip the "www." off + String t = str.substring("http://".length(),lastSlash - "http://".length()); + if(t.startsWith("www.")) + t = t.substring("www.".length()); + //(4) Check that after stripping we have either "live.com" + // or "google.com" + if(!t.equals("live.com") && !t.equals("google.com")) + return ; + // s survived all checks + assert(false); //return true; + } + } + } } diff --git a/regression/strings/java_easychair/test.desc b/regression/strings/java_easychair/test.desc index 8680af72c5a..14418a7798e 100644 --- a/regression/strings/java_easychair/test.desc +++ b/regression/strings/java_easychair/test.desc @@ -1,7 +1,7 @@ -FUTURE +THOROUGH easychair.class ---string-refine +--refine-strings ^EXIT=10$ ^SIGNAL=0$ -^\[assertion.1\] assertion at file easychair.java line 29: FAILURE$ +^\[.*assertion.1\].* line 30.* FAILURE$ -- diff --git a/regression/strings/java_empty/test.desc b/regression/strings/java_empty/test.desc index cab514b80b5..44e8e1346a9 100644 --- a/regression/strings/java_empty/test.desc +++ b/regression/strings/java_empty/test.desc @@ -1,8 +1,7 @@ FUTURE test_empty.class ---string-refine +--refine-strings ^EXIT=10$ ^SIGNAL=0$ -^\[assertion.1\] assertion at file test_empty.java line 4: SUCCESS$ -^\[assertion.2\] assertion at file test_empty.java line 5: FAILURE$ +^\[.*assertion.1\].* line 6.* FAILURE$ -- diff --git a/regression/strings/java_empty/test_empty.class b/regression/strings/java_empty/test_empty.class index f0ced290ee36f38aa83f6b0d1a25161f3594a364..147a2b628fe75ae1487deed1d827639b1d4b3295 100644 GIT binary patch delta 337 zcmYL^Jxjw-6o#LhubZYxZBnhNTCG(Ea?p(M1ObcYj0ZWWiY+RcOJ2 z?*1BofQTm-tjl}Pd3it1eQ>AF?&r_jJCL&#P^0a$SVNNrbXd|X2e`B~D*;_rHEU%) zh@+$1;{58cxH&G)t}isb@@c0P5-A7?s0$OaPQU!hyp51e`oo^u9$u=wJ1rfcnrWqz z$wrAM5^TuUl~+P=vkB_C5;7;~8B&S0Ig=h>8Mc#HgBR=(NjAp0r#{6!nc#g?cFWis z(ju9H-YKbkE|%3teUoYunOd{d++;$W=rR5X?L6Yxuh{=-f5%iIE>^f-ojh;K7JdP7 CE+hE> delta 433 zcmZXQOG^TA6vcn@a&#Qc#z&S~(_1aDs8&I=&sIhdt)>T3nM6pdpbyYW+6k>&SD=tk zdp}Y{bY~!2#D#m$|8P0y{BK`>G}Z^-Z|}ewWebaJnDGcCD6Ur3OKSQ3{$BCmo> zMW#{ip*;JGB&3G|QX#@9j$nWF1XT)F9ku#`)*-#rMekyCi1rB`^e{gH-VuIC-U{pM zs)4S9E?AS&rw*REFfi+2t^gPF`tsby z3m1-#FSvM#MH@9jr52>ANR;fw={uPQovw%obU?5+Wh~VjLax5DPcXN8ksy?sG8P~E z#~qRE>0}NZ2Qns%wNwy(+YP>FZq`6>HpA{6hTH1(lTf^uy24i?RbNCLr9Y+mx^@)& z2t1TfCX}_k-VNfz^_EIxe8})yoiNhjR|G>_V;J|agk?f?l)ZJ|#7>g*5?1qo!baW0 z3K|axK6Q>ns0fqw<_PCM>ucSxqXm9ufsdr{h)Scv?Jm!eFcpbZCL$W@;i;%T2Y84F zSm3wt_@$^^)orkq1EZkK`vl+S_#{5_jRELfC&K65%AAA(D#O$^ml_lBs7>J{u06tCg52Ppj3NJfU_!(=fW-g+ literal 0 HcmV?d00001 diff --git a/regression/strings/java_endswith/test_endswith.java b/regression/strings/java_endswith/test_endswith.java new file mode 100644 index 00000000000..fabf6f8dde0 --- /dev/null +++ b/regression/strings/java_endswith/test_endswith.java @@ -0,0 +1,9 @@ +public class test_endswith +{ + public static void main(/*String[] argv*/) + { + String s = new String("Abcd"); + String suff = "cd"; + assert(!s.endsWith(suff)); + } +} diff --git a/regression/strings/java_equal/test.desc b/regression/strings/java_equal/test.desc index d66c30b26fe..bb61dcea8ed 100644 --- a/regression/strings/java_equal/test.desc +++ b/regression/strings/java_equal/test.desc @@ -1,8 +1,7 @@ FUTURE test_equal.class ---string-refine +--refine-strings ^EXIT=10$ ^SIGNAL=0$ -^\[assertion.1\] assertion at file test_equal.java line 7: FAILURE$ -^\[assertion.2\] assertion at file test_equal.java line 8: SUCCESS$ +^\[.*assertion.1\].* line 8.* FAILURE$ -- diff --git a/regression/strings/java_equal/test_equal.class b/regression/strings/java_equal/test_equal.class index 26ee19e6cb16d81855e5204569a842332489e8e1..e0fc6db8aaf91eb799f5e02cfdd3194a232479f1 100644 GIT binary patch delta 72 zcmcb{dX<&q)W2Q(7#J8#HgbeBiLx?qF|aX+Ft9U-GjK5IGH^0DGjL5VVN&8UVPFKR ZVqg#yn!J!ngO|sF5hx%56kuYI1ON?o3Zwu4 delta 73 zcmcc0dX1Ii)W2Q(7#J9gH*$nCiLx+oF|aa-Ft9O*Gq5x0GH@_BGjL8WVN&8YWncuV aVqg#wW|+KyNrRWyfe|Po0Tf|kkOTk~K?Sac*Pan#mw9$s)uJ zW{FC&3h{th+`AcgBeyf~?cWI0z{DU9B+YW4FZBflZ99`czGNcfdX2x1|YiVq;xf{-SajacLbY(lEL7l>^P zL{QLDu=N3a0&6>UBoUkJE;GZ-|9`vtX-{d#x;Is>~C8Zr-`4a>HrJve$F9;h_7 z$GwYguX}l=sI>p;$*H4v|(Q-S8 diff --git a/regression/strings/java_float/test_float.java b/regression/strings/java_float/test_float.java index e59c631d91e..312f1aeaf10 100644 --- a/regression/strings/java_float/test_float.java +++ b/regression/strings/java_float/test_float.java @@ -1,20 +1,17 @@ -public class test_float { - - public static void main(String[] arg) { - float inf = 100.0f / 0.0f; - float minus_inf = -100.0f / 0.0f; - float nan = 0.0f / 0.0f; - String inf_string = Float.toString(inf); - String mininf_string = Float.toString(minus_inf); - String nan_string = Float.toString(nan); - //String arg1 = arg[0]; - System.out.println(nan_string); - System.out.println(inf_string); - System.out.println(mininf_string); - assert(nan_string.equals("NaN")); - assert(inf_string.equals("Infinity")); - assert(mininf_string.equals("-Infinity")); - assert(!nan_string.equals("NaN") || !inf_string.equals("Infinity") - || !mininf_string.equals("-Infinity")); - } +public class test_float +{ + public static void main(/*String[] arg*/) + { + float inf = 100.0f / 0.0f; + float minus_inf = -100.0f / 0.0f; + float nan = 0.0f / 0.0f; + String inf_string = Float.toString(inf); + String mininf_string = Float.toString(minus_inf); + String nan_string = Float.toString(nan); + System.out.println(nan_string); + System.out.println(inf_string); + System.out.println(mininf_string); + assert(!nan_string.equals("NaN") || !inf_string.equals("Infinity") + || !mininf_string.equals("-Infinity")); + } } diff --git a/regression/strings/java_hash_code/test.desc b/regression/strings/java_hash_code/test.desc new file mode 100644 index 00000000000..4f786d42f80 --- /dev/null +++ b/regression/strings/java_hash_code/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_hash_code.class +--refine-strings +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 7.* FAILURE$ +-- diff --git a/regression/strings/java_hash_code/test_hash_code.class b/regression/strings/java_hash_code/test_hash_code.class new file mode 100644 index 0000000000000000000000000000000000000000..d9b3e2b2f3de9b4d49d84348b75a7e50690e3cc1 GIT binary patch literal 602 zcmY*W%TC)s6g}6EOmGYY2SR8|c_SVYY*?ZS#6v=*Wf5AbY|z9R!9Z}3?eHoK)T@a{v7{V8UuO3{K1-^M0#&>}c zLTOSaiHcL*jFNSo$XY|y3A9JZE$c|9KM3~B>|cVj)~qW+@3xNA@7768#k;1M6DLwf zgzjo8!{cA_Gz$xi67tJoi zm&l`!BL&biMg#)>I8wz$6N!Z6BbOxO3I6bp;9q zwP+Ev?z^;;&IlRza?ZVf{*QCM?H^K7!gTHjg3J? zob-fxh9+XDcv{2L52~93jGZUUKB=N{PvVu>=@9EZa?!>v8BDIlTVydgmgL*Aa2!u4 uE^0*CVn(hKe0CC4ABRKQvj@ccSjGc}{*3wW{5M}@WTLsd(H3*#;LI=X>@Jr8 literal 1108 zcmZuwOHUI~6#i~IGj}>|X=y2s+6pLYAH1|sUr02lu?ffmqY)EvXa^h|I%Z}tCjJTC z7{kWyTtshJ`=DAK_0>&mAb0z%0(W_q*RY_nhzC`T6I|Hh>Z?Xo%ssihd0P z7!>A&Feil>QgKT7)54qyA&MMFUPBniISLwz80HvZNDk?)YdD^1*WK%;t1nwdje#vP zC{t$L^rjhtx%^!QX~wP@46#|WZrt8jUpAaOf=mbNx>;xF&OMl2)1T>MmR?^STkssS zzIs^%Mi)H2`eaUj>hn29ImQ^&sj9V?Ut6#@oT_ot6xkA<;d)DEy=FXLvR6h$#t0Hf zGDL0}mSqpzvmL88NI4=H$Jq$Z2{Vq8Sd|z8mMyjuVoN5DPKMrgUDsO8-f$e-q2dl) z$1xc}8Rr?|?U4E9HKXd0Qb+W6fVkT;1NW<+Um*p5 zf(SSXs3Jr14MD>&{bv(|UZUB|p#zU-GAlHj7c`fb#C%Oz-jnd((Tg4Q;TO{QjSLGQ z%ev7|D9CDmDLBN@$B|~cACO3QrMvo)$s}EOY=6j;{xs<{iD(lYo8ZzrNWst0+C{e} RE|SX#M6Zf>k@0)V{sT&*+!Fu* diff --git a/regression/strings/java_index_of/test_index_of.java b/regression/strings/java_index_of/test_index_of.java index bbe06d279ec..b607ba79570 100644 --- a/regression/strings/java_index_of/test_index_of.java +++ b/regression/strings/java_index_of/test_index_of.java @@ -1,32 +1,10 @@ -public class test_index_of { - - public static void main(String[] argv) { - String s = "Hello World!"; - char c = 'o'; - int i = s.indexOf(c); - int j = s.lastIndexOf('o'); - int k = s.indexOf(c,5); - int l = s.lastIndexOf(c,5); - int m = s.indexOf("lo"); - int n = s.lastIndexOf("lo"); - if(argv.length == 1){ - assert(i == 4); - assert(i != 4); - } - else if(argv.length == 2){ - assert(j == 7); - assert(j != 7); - } - else if(argv.length == 3){ - assert(k == 7); - assert(k != 7); - } - else if(argv.length == 4){ - assert(l == 4); - assert(l != 4); - } else { - assert(m != 2); - assert(n != 2); - } - } +public class test_index_of +{ + public static void main(/*String[] argv*/) + { + String s = "Abc"; + String bc = "bc"; + int i = s.indexOf(bc); + assert(i != 1); + } } diff --git a/regression/strings/java_index_of_char/test.desc b/regression/strings/java_index_of_char/test.desc new file mode 100644 index 00000000000..30d179cbaaa --- /dev/null +++ b/regression/strings/java_index_of_char/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_index_of_char.class +--refine-strings +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 8.* FAILURE$ +-- diff --git a/regression/strings/java_index_of_char/test_index_of_char.class b/regression/strings/java_index_of_char/test_index_of_char.class new file mode 100644 index 0000000000000000000000000000000000000000..bf4fa6e946eca6e5f9872d09a06a2f839b17d288 GIT binary patch literal 614 zcmZWmO;6iE5Pg%_*kOZP&1R^$!B?%hXrN{9`a z#Cn_Uknuj|@Y;umK|;-@S35F3THSnZ_k%HsAyob+6L{le9&ZUjAGg~+R$=x}sF@iZ z9}z^}%I+b1S=?FLVUvB>R)^<9s75N)Mnye!cAIrM!NWP=Mg>nBprB^^krnVA(S2%sIkQ5A=k(K!x}>FxpdD%awtVinv4h62iHLQ~Uv^Py5`Q PrEyX4H>`!RTy^{pE-iAY literal 0 HcmV?d00001 diff --git a/regression/strings/java_index_of_char/test_index_of_char.java b/regression/strings/java_index_of_char/test_index_of_char.java new file mode 100644 index 00000000000..92d75b3b07d --- /dev/null +++ b/regression/strings/java_index_of_char/test_index_of_char.java @@ -0,0 +1,10 @@ +public class test_index_of_char +{ + public static void main(/*String[] argv*/) + { + String s = "Abc"; + char c = 'c'; + int i = s.indexOf(c); + assert(i != 2); + } +} diff --git a/regression/strings/java_insert/test_insert.class b/regression/strings/java_insert/test_insert.class deleted file mode 100644 index 5fa0f4250618e78cf024e8037a9213b4fe087127..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1318 zcmah|TTc^F5dKct?J3I^N=t!?C@4ycN(BU!R^+bbt|c1q!7S|wENolcZcPl2`X}TM z_$($%B8k5HZ~O!5oE9jzNR!UY&U|w@-Gvy^0&hg^&zG~L5~!7 zq_``^Jt=y9h)aE6ioRO(V?e_L4AvryAs-%Uc!b9s!x}>9=16Er;t9tHL#WFr7KQDY zg?w?+EE;Q;$TF~125-{Ln+`#0qOn&D%0wY67#ilxyjUpZ)`Yz*!4$|DW}cxr`ets^ zcyGilBflO`JGPl$Psl`n+A%U)^Tu`=&+(Lw!ZFI=OJ=OY7FxPcvNK}Zlm!EhC^~P= zyd0}nmeg?tZ451E%a4~#D=TaUbwgNILBhs#jAKHINhzkJn5H8bYZ+-i)A1ZBju{=Z znB$n&u^@9=5g{rz1i>7;B>MUX;`FDQG^mb6EHSiJyN?|)Hf7rdYF~F^V2&3$ULsA$ zs3t6~ZHkOT9WJ2g6tF@YLpXXdm);614DHcWDs~QYNJyd_pSUDGb4h&lfAQXE>Rk84 z{}Oyo;plKp(epqW`2=6-4@F1h=-LV;Vl7_@vR{qPFZ%U1-t>*16EhaN!^3d#I0a7Y%y|>>?cD!A2Ls zUDO>Qw6c$;pQrqvtA07Dr#$Hh8pu}YSSmQpT}QH>=8VwnozT!jo_^>^z>i6a%o0A0 z0JhMGj|ifJvRmN!OAgM_$rQ#oZgAX`ZXddinHnrp0t7<{yJ+48SH3{0`G!Dsm?PR` QQ57Els3i9meRy#D9{|H4+W-In diff --git a/regression/strings/java_insert/test_insert.java b/regression/strings/java_insert/test_insert.java deleted file mode 100644 index 6871a51716c..00000000000 --- a/regression/strings/java_insert/test_insert.java +++ /dev/null @@ -1,19 +0,0 @@ -public class test_insert { - - public static void main(String[] argv) { - int i = 123; - long j = 123; - char c = '/'; - boolean b = true; - StringBuilder sb = new StringBuilder("hello"); - sb.insert(2,i); - sb.insert(2,c); - sb.insert(2,j); - sb.insert(2,b); - sb.insert(2,"abc"); - String s = sb.toString(); - System.out.println(s); - assert(s.equals("heabctrue123/123llo")); - assert(!s.equals("heabctrue123/123llo")); - } -} diff --git a/regression/strings/java_insert/test_insert1.class b/regression/strings/java_insert/test_insert1.class deleted file mode 100644 index 80091936cea37ba88b8d3f67bddf5ea8683f7b2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1035 zcmZuw+fEZv6kVsx%xR}n=!F6mQ9;xem2wf(wsMC^f|sO513s9cJ%PdL49-kV41dC# zPdbd2DB1aUkF9GfkY zgTOuE>dsyU65@=!@)ti4HF`z2P9oDSTFcG9rUwd$Mwm6akZSrlzsr9lAgI#;_0t9hsWX$*!7SbAcJc(m(Z_tHB94be6Q4v(0n{Uttiv#5tQ|$dI+tc zWi++F0sbzdH4rZF14J^s0sR2ceWWuyX*3YqNAw7t>xbz2Ez^aX=|-T_T%iOiI3V diff --git a/regression/strings/java_insert/test_insert1.java b/regression/strings/java_insert/test_insert1.java deleted file mode 100644 index 54e754302c5..00000000000 --- a/regression/strings/java_insert/test_insert1.java +++ /dev/null @@ -1,23 +0,0 @@ -public class test_insert1 { - - public static void main(String[] argv) { - int i = 123; - long j = 123; - char c = '/'; - boolean b = true; - StringBuilder sb = new StringBuilder("hello"); - sb.insert(2,i); - - /* - sb.insert(2,c); - sb.insert(2,j); - sb.insert(2,b); - sb.insert(2,"abc"); - */ - String s = sb.toString(); - System.out.println(s); - assert(s.equals("he123llo")); - //assert(s.equals("heabctrue123/123llo")); - //assert(!s.equals("heabctrue123/123llo")); - } -} diff --git a/regression/strings/java_insert_char/test.desc b/regression/strings/java_insert_char/test.desc new file mode 100644 index 00000000000..f5727a3a4ab --- /dev/null +++ b/regression/strings/java_insert_char/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_insert_char.class +--refine-strings +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 8.* FAILURE$ +-- diff --git a/regression/strings/java_insert_char/test_insert_char.class b/regression/strings/java_insert_char/test_insert_char.class new file mode 100644 index 0000000000000000000000000000000000000000..fbf4a82070b0507614103af7be1f1d5846d7a754 GIT binary patch literal 811 zcmZWnU2hUW6g{&nyRd8vrIg|aYPIS@75u2a&=?gpG1B^g(X=nkuuR&i+eP=o|6>1u z&uRjRP4wOWr11_EHnuN!XU{!z?z#8Q@4r8O0$9gG3-h>WqME@a3mPt~a7BfcENooO z;F^V1TsLvUf~A-@EjXx|s530C@-P%ZBnN)@OoqJYi9Q3{VK6qNFQZ2cDW~?9L2nQG zf+63LzSxQndm?zF$dowb(r1|KM%;bB$v=!?a${nRA+zCnCo)!d5C^V!A=Ra&NQBX@ z^i}Cycb^B11OAEISU{0sS)H36_xGCJD3Jc%(^z_a5in@nRh(NkZlhtNi90s(D3C|q zbE%+>yST?tNd%ruyL%o415zlQE^OkyO+$P@spQt{-hptV|DcHza_)2z-UMu^`52RC z7^=?8cI^!3q=goZBpOV$O3qm#F%0oB=3aQJ*2Gh*Mytsu4%!~=kD=Tbp$tTS)-G)$ ziYY}3sl6HIcLB5X6BnYv%e3&{{%3Hs)i&cIWERAr6Gh%%3M|^lfV^B zYq*MR0)5EEk=Ibb497JMx{8_AP{ehP8w`UP;rr4HEZ6ZLTfV5<(qv$346(B1Siw9) zIGcOJ5UIMRWawYA9QmTzs7vp)B9o&bEQg`D76{}0ve<6Jq>JMw$1R3<*|3i?X*IX$ z8S<&6;>H5$2OE~7s&5$Ygts9)PwdQYiH}0ZAkqvY>Rz;kvstVKp5<&-nwD)!k0B&X z#hKG_8+UZv#XXMuIv$|JQP%NLc?OUob)s&Vq(jF%9x;q|GcF$Y{lxQJN;&+0Jsb-< z7ExhHc4J@Gx1d%yrYs~D7(}pcfgVwVyx3H!$kJkdNp^3bktvorWUxz$*os7@{T`Gi=^_4;-X{_WUg%+Z3^DV@d z_rPabi0>h>i}XxNYoX^edJdqk?xXjYDimrLnx+y|9U7JF11Dv1j1o3UNCrLh&*-S2 zmoSi@9iqZ!i}#;8@3Mr|Y9%njwM=pi9iuDmA1H+x-4 z$h4F%xBG`38NAYDzBm-hC(N}Y;l6(?V_}Vu+;F`U8N1!<2d;ds^rL(v!|1K@ zb!uLs+JX2a94sJ5Sl0WxC;a_-I|`J)|D>Eu@k~lxi#aB!KQAHIj)6J zDsOF7&TvjjXmUrQ-b5>3K1*bVDL?jw7oN&B_SCHKWHK`cn;wskQ0U4~1+qJ>mWL7b z`GRM+hZX(>^ZZpPTh#61T@0jq&2f=WC0>cwM0E)Is)@*RG)EvIg{3L=9X~bru6_(- zHy0Zs{-PSsRtHGD;b6AD!8$^IEtec1^%?17*t&9g zixCf_eb*PI_dBr{xknza99r)!9ka+YEQoj2v;2cyf4wctY!v;fP47GLE>(e0U5?20SG!)#^aUTyDa^uWb?L%%y zf0%~680O68IBsaHi;1O%?J*S1?M7)L=Cq+YL&e;l@YesAphn%Z;(2p2kRVh1U2J*b zU*v{O)JwG8?3i-HqZ445cX;Rq+!@V?78=Fmp#AS*g)S*aXUB2{F=TorK-Ysj$vOHJ zNi)*Pav$uI2*fv^Rk??dr0n-Wh2#tvQzFsZGJ}j z82L3r>ml<2nG@){eN259;L-qmiQuUsG|~nXEJ4LGm8y}YK%NZPPt+7F4qfL)4Auv% ifEi=DhwL#F`6J}S7o^A7XT$|g5|aK%w0C|`y7(LCDZnTI literal 0 HcmV?d00001 diff --git a/regression/strings/java_insert_multiple/test_insert_multiple.java b/regression/strings/java_insert_multiple/test_insert_multiple.java new file mode 100644 index 00000000000..c976ddd807f --- /dev/null +++ b/regression/strings/java_insert_multiple/test_insert_multiple.java @@ -0,0 +1,11 @@ +public class test_insert_multiple +{ + public static void main(/*String[] argv*/) + { + StringBuilder sb = new StringBuilder("ad"); + sb.insert(1, 'c'); + sb.insert(1, "b"); + String s = sb.toString(); + assert(!s.equals("abcd")); + } +} diff --git a/regression/strings/java_insert_string/test.desc b/regression/strings/java_insert_string/test.desc new file mode 100644 index 00000000000..91e13cefab1 --- /dev/null +++ b/regression/strings/java_insert_string/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_insert_string.class +--refine-strings +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 8.* FAILURE$ +-- diff --git a/regression/strings/java_insert_string/test_insert_string.class b/regression/strings/java_insert_string/test_insert_string.class new file mode 100644 index 0000000000000000000000000000000000000000..be8f7ad0f79126964af9df57d0e5500d86d69cdd GIT binary patch literal 841 zcmZuv+iuf95IyT$>^KfdoiquT0)+xe3JI5Rky0U`fP@I}5Cm#ps*SxWTU-Zhhkv0z zz%w8v5|!Yce*!VIU*?2gZzJ#%KpKYxGw4xo)YCh}O(aoWHc6B^DMSXK8qb)3&2 zhcyEiOkBhz9W@hKMXsA@U|q*$hT<9zLlH!B;D--o$ormf8Q3;MdPDj$y33HL)n73r zHwUg@$akeLo)7o?B6z9Dl-TFeXUO#;?!0}*-^DN)(s6~s*l@ff8M8MS299_v)uT!z z!e~eOs`O461=8Pb?(q-Yf{h}jRowEpzuW4?$p=H}xgucDxT`o#iu#U)7Oq;jhU*pz zSRyaH@3>Uh!VR<;s&kq9(=Hzc!GLt^MFTo+TDXPV42Ai-7yUiqM1MgOM-0og?wmIP zJ8DwtNm~rf+LQk<7NDcvIy9|lFcmM=>I+0-q{aIo_riaQPfT{|w6*-)(xykNWhlEM zl!0((6QD&!LrTzIx3NlpNS^*AR;a2GQj`Eq2Sqwd^tD1aqdV0YgMC&+EYq2eL52*< zGwK_9s!^_W2yM$wjFEiWNZP3p(ytpM=-n?c4p3URGb5NEkv&9qYYgj$64heSGEx+$ zV3NEI9Tga8Qi%$oS+HMd>Zs~CPVk9Y)pqOzSh8~?96NxX{DfrUD~!4B)U47;L9_0u KmQKcHPyGQmzOiip literal 0 HcmV?d00001 diff --git a/regression/strings/java_insert_string/test_insert_string.java b/regression/strings/java_insert_string/test_insert_string.java new file mode 100644 index 00000000000..028a348122b --- /dev/null +++ b/regression/strings/java_insert_string/test_insert_string.java @@ -0,0 +1,10 @@ +public class test_insert_string +{ + public static void main(/*String[] argv*/) + { + StringBuilder sb = new StringBuilder("ad"); + sb.insert(1, "bc"); + String s = sb.toString(); + assert(!s.equals("abcd")); + } +} diff --git a/regression/strings/java_int/test.desc b/regression/strings/java_int/test.desc deleted file mode 100644 index ae60dd78af0..00000000000 --- a/regression/strings/java_int/test.desc +++ /dev/null @@ -1,13 +0,0 @@ -FUTURE -test_int.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_int.java line 8: SUCCESS$ -^\[assertion.2\] assertion at file test_int.java line 9: SUCCESS$ -^\[assertion.3\] assertion at file test_int.java line 12: SUCCESS$ -^\[assertion.4\] assertion at file test_int.java line 15: SUCCESS$ -^\[assertion.5\] assertion at file test_int.java line 18: SUCCESS$ -^\[assertion.6\] assertion at file test_int.java line 21: SUCCESS$ -^\[assertion.7\] assertion at file test_int.java line 23: FAILURE$ --- diff --git a/regression/strings/java_int/test_int.class b/regression/strings/java_int/test_int.class deleted file mode 100644 index 643d7eca09cb890b7b49705679a2c8406c96efa8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1140 zcmZuwOHUJF6g^)%ueMV7Zru1Y+~J0(cczq9bo0ILJ?Gwg&dirz?>_;^;F2E-y8Y-uuOFvz z#)lU4i8$*Ak8TO)oXB|z2`}*at8+<8=yx(xA};tbfI$&M4ADN-vNY4yD~5GNx72)D zD>ATU24Pw^bbFS;n@HYa;1()HjUlwC8`{n4T3$16JINGSQ+0!(EpcygRehuml~toO zv}BvQQJQjq!6jQQJh-8*yZIu9MT{^=(}nUOzkjJxH4EA`-C+ybnq{x(hCS$z$%vv= zL|UeSvxJi|iZK~sL>Sr|)#mCWTs6&#NiB_}Gg%qqxX8c{WYZY}P9RGGHD4&on8Xxy zP_HCnTE+}$Ql&w8E5E80Y|`gHQ~i}#o0K8kz~&5FD{0h+WLN6pSR$AFS07Tja9=g& zs1Qd93j|qLO-myNhFIcXKr+V=uq)TK$8};sdstP=*0Jmp-g6zRYlFx zO|5t&8#!cGDL_syqnAD;g+4K+v^zr6$qUi}t+dAI7N?!j&iC(vy>SxJMyudHGWc); z?R2J8wgC^_fuCVtau1%x6t@HKOp2#E{fRR8cyegoHto zXC49MAY+AeFCl~{r213R{W&TAl4Sfyg6@-~9mJM^_?tjHp+%fxjC_b5ppzY-hwimg u7o8@EyYtAgQP&zE5=F}nLYok|SKz$wz%@Fo+vil_;R#-LOpdz)bo~Lq)9aJ~ diff --git a/regression/strings/java_int/test_int.java b/regression/strings/java_int/test_int.java deleted file mode 100644 index 620ae638dce..00000000000 --- a/regression/strings/java_int/test_int.java +++ /dev/null @@ -1,25 +0,0 @@ -public class test_int { - - public static void main(String[] argv) { - String s = Integer.toString(2345); - char c = s.charAt(1); - char d = s.charAt(2); - char e = s.charAt(3); - assert(c == '3'); - assert(d == '4'); - - int i = Integer.parseInt("1234"); - assert(i == 1234); - - String t = Integer.toString(-2345); - assert(t.charAt(0) == '-'); - - int j = Integer.parseInt("-4231"); - assert(j == -4231); - - String u = Integer.toHexString(43981); - assert(u.equals("abcd")); - - assert(e == '2' || i < 1234 || t.charAt(0) != '-' || j != -4231 || !u.equals("abcd")); - } -} diff --git a/regression/strings/java_prefix/test.desc b/regression/strings/java_prefix/test.desc deleted file mode 100644 index 175f934ca1d..00000000000 --- a/regression/strings/java_prefix/test.desc +++ /dev/null @@ -1,10 +0,0 @@ -FUTURE -test_prefix.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_prefix.java line 14: SUCCESS$ -^\[assertion.2\] assertion at file test_prefix.java line 16: FAILURE$ -^\[assertion.3\] assertion at file test_prefix.java line 18: SUCCESS$ -^\[assertion.4\] assertion at file test_prefix.java line 20: FAILURE$ --- diff --git a/regression/strings/java_prefix/test_prefix.class b/regression/strings/java_prefix/test_prefix.class deleted file mode 100644 index 6f5f4025932b51a8fdcec8d94d4d5032d883ee5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 933 zcmZ`%%Wl&^6g`vJvEw*RaBwh`LIVNvC=IW60il8x5J)L30*#t3kdv6=;@Xw%ApQV; zfvmb?4M>edrLgC7_yFLJMH)asvgY2IbMBpc&iLDpFCzfgv7{h_GZN0qm{$-(LB=^5 z=XqL`ae>E+Nu+T}LP8>W+~A%am>tLJF|am6qHeo(xWW)G zl{XlKHLqteWE!?>J?`&zEdMDd6R>OAEELDw`wTRlY0^7HGN8^*lVV?kc zsx}Jr*ctjYSk~ZzDT{+~7im3CyE%%CqF5P%edI*wv?iiMh9vShK{=;>r_uz)cZY~= zYVje2h9<68wZs9WmFfbm%R*I?X`5UYD?0ov-S` z0JkSVVhogZae(3kkj6k(7vCc_2KcnGXxf{YpyCRAPFBJ#6Lrs UOfvS3cNGy!-{J0_js~6k1sUzW1ONa4 diff --git a/regression/strings/java_prefix/test_prefix.java b/regression/strings/java_prefix/test_prefix.java deleted file mode 100644 index c9b5fa72fcf..00000000000 --- a/regression/strings/java_prefix/test_prefix.java +++ /dev/null @@ -1,23 +0,0 @@ -public class test_prefix { - - public static void main(String[] argv) { - String s = new String("Hello World!"); - //String t = new String("Hello"); - //String u = new String("Wello"); - String u = "Wello"; - boolean b = s.startsWith("Hello"); - //boolean c = s.startsWith("Wello"); - //boolean b = s.startsWith(t); - boolean c = s.startsWith(u); - boolean d = s.startsWith("lo",3); - if(argv.length == 1){ - assert(b); - } else if(argv.length == 2){ - assert(c); - } else if(argv.length == 3){ - assert(d); - } else if(argv.length == 4){ - assert(!d); - } - } -} diff --git a/regression/strings/java_replace/test.desc b/regression/strings/java_replace/test.desc deleted file mode 100644 index 1e89ebe37b4..00000000000 --- a/regression/strings/java_replace/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -test_replace.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_replace.java line 6: SUCCESS$ -^\[assertion.2\] assertion at file test_replace.java line 8: FAILURE$ --- diff --git a/regression/strings/java_replace/test_replace.class b/regression/strings/java_replace/test_replace.class deleted file mode 100644 index c795826dc15e95c6e64931bc9afb74e3617f8687..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 904 zcmZuvYi|-k6g|UhV7mx~wqg|ptqK&uTI-9(*r28+R8258tsl$+lV~aL$K@!l z$iouHRRu9*W4MOv3JNH4loTwZ%yEMuy`(vguwC6UoyWSPwG7c=V7m;Fb=}n6hYZ0& z@ijxJZgm7hqM@7Oxz}w8`;|HadBk zR#8#KO%+MZj-y^~+Z#n!aEl=`0ogd}`H5{?Hpi-p+gRhcqv9?q^n98K$2}GI@!$lF z7p;BKb{Xai|L>ZQyO6@v>&1VQNMP~a(+uYn#t67pBnPIu{^+=(OI}!>EINYIt?EmX z*(I@s)~%75eupQo8F)`78RSu7qCnjs--%pDIJzx5$AXYqu15hfeHVH9ND2CAESZtA z(k=)l9ie%SPFY$Rt>MxT?5j+~Jk1gRlF_eQz**YM)KBy@Nb9ph1a?xvAwrGiq?Pmr z2yY!A(#Kpm#RrJ?F>{F6&JfDa1I&~MP^Y7xCsA20;FnvZfHR zP((%GH%c7mXk_Vr@tFUbPZUU{5g*`8A3XF0q2M<}Cg?}aNTe_V@kg@d^M3IQe*s01 Bzfk}H diff --git a/regression/strings/java_replace/test_replace.java b/regression/strings/java_replace/test_replace.java deleted file mode 100644 index 342bf9afddc..00000000000 --- a/regression/strings/java_replace/test_replace.java +++ /dev/null @@ -1,10 +0,0 @@ -public class test_replace { - - public static void main(String[] argv) { - String s = new String("Hello World!"); - String t = s.replace('o','u'); - assert(t.equals("Hellu Wurld!")); - System.out.println(t); - assert(!t.equals("Hellu Wurld!")); - } -} diff --git a/regression/strings/java_set_length/test.desc b/regression/strings/java_set_length/test.desc deleted file mode 100644 index 43f82a648fd..00000000000 --- a/regression/strings/java_set_length/test.desc +++ /dev/null @@ -1,9 +0,0 @@ -FUTURE -test_set_length.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_set_length.java line 8: SUCCESS$ -^\[assertion.2\] assertion at file test_set_length.java line 9: SUCCESS$ -^\[assertion.3\] assertion at file test_set_length.java line 10: FAILURE$ --- diff --git a/regression/strings/java_set_length/test_set_length.class b/regression/strings/java_set_length/test_set_length.class deleted file mode 100644 index 8836640967a8736f8ecdfc31c509c8f67e5cdc31..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 887 zcmZ`%TW=CU6#j+<29~8=xfL%|t5uhRMXmJ`8>6BoO{hL#G~h$Cz=UqyE@pS|$22iM z`m839*hJs`Pa4l`OHtI9GiSazm+w1gzW@C46~G$q=$J!^V=;lVIwCly%#t$alQ3{W z$1*N*T+)$5NnI{;SUSpB;ixcVm+c@BzH|m&@W=`5jw^Z$tj!SLa6CueW6-Sf3x;TY z&=U;v4aXBthkG62KUcx@uxC3SL&190*tOrd)}2NS`MeShE^xPf)jHPe^lrh!|y&0tP5pLKRcSN;JV z3T4P!|5l$QDUDDGP0HF-14+oiBr9i?|4w7j18Ms*c9pG^`lrCE1r zr?iot2pnJZj`h+a;$8!v2fk; z7RD>SReQH)H3K~9Rx!t*E!65K{CcI)a%=pVkZd`hd;X>uly6pBqHc3{O7a>QLY5)> ze~-t<7zVZJ@-6W`Z{QB@QiJ@iuqNr$Qiwx@_P{l(7i&$bvcBx)ecX-V|lR9>VthJg=B4(H@^ziIl>SRRH zp!tmsN2X9b2PA~<`IhT@>%xD_FxZQpu2!SwCy+!}@JgMY0$rrdJ>hcu)C#&kzeOMD z9c*BP9#@*)Axq|@m$XwrHOSJMqth@&MloU@fPIlbT%a`?BpG73h)cAW&|g%lQ2b~f zMLuEg5TVxxP|D+}a2t{JaWgy}#8i}m8IgyS8f4ng*1jUPkIY0$Z=-J?eTOipIR2xP z?r$T}Bb_{pmij`0J`+0a719|-KO!_(ltxieqWmoSuuA_>6>)q(0+$Jyfbs{cDuz{D v8Tw80Yq)yq!CWvbkV<2qjnqEW@MnaTZ-{jpb_|hZ5rpE)(zZMuLKyi6M=96L diff --git a/regression/strings/java_string_builder/test_string_builder.java b/regression/strings/java_string_builder/test_string_builder.java deleted file mode 100644 index 1d76b34e9f8..00000000000 --- a/regression/strings/java_string_builder/test_string_builder.java +++ /dev/null @@ -1,16 +0,0 @@ -public class test_string_builder { - public static void main(String[] argv) { - if(argv.length > 2) { - StringBuilder tmp = new StringBuilder(); - tmp.append("prefix "); - tmp.append(argv[1]); - tmp.append(" middle ").append(argv[2]).append(" end"); - //StringBuilder tmp1 = tmp.append(argv[2]); - //tmp1.append(" end"); - String r = tmp.toString(); - assert(r.startsWith("pref")); - assert(r.endsWith("end")); - assert(r.startsWith("pr3f")); - } - } -} diff --git a/regression/strings/java_string_builder_insert/test.desc b/regression/strings/java_string_builder_insert/test.desc deleted file mode 100644 index 2655f846da1..00000000000 --- a/regression/strings/java_string_builder_insert/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -test_insert.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_insert.java line 17: SUCCESS$ -^\[assertion.2\] assertion at file test_insert.java line 18: FAILURE$ --- diff --git a/regression/strings/java_string_builder_insert/test_insert.class b/regression/strings/java_string_builder_insert/test_insert.class deleted file mode 100644 index 69a32d7f93fa8cbebd4e1f6c84f79c41463bb3b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1049 zcmZuwT~8B16g|_Aop!sWYg<1206|e&3RFcJe$32GBpy7GK^-ah27EI6Bv_zGGturXorfvE& z48ctHHAATAR0Ts~$+X2vy|yXbR}xGIHN&(Sx-uI}+r~#DZyEMhzT~^6y;YEf@se*; z-Y*+FO+3dqY38`k5Sgx6M^~sNr|wq7GgA`kzVQ6FrY&WSNlFbVq#3%;)6dsUt14WQ z+W*OMt*XRLXqdzU4G-~%V@g8-(;SaA%*c~VNHWA0g=IOd3eutB31%63+T?S`4SDLi z4zb5h>EW2uFpnasY!|%P+!hs|A+T{a-)aIwXXgK%QCc1u`ZCWqirEXGBYy>ImG2yr zr85_Sgg7Oq^x5-8jo!_vlc>%Xt?A@n(v$c^Ba9jqq?-EArWyE-1X=W+iuh1BEbpB9 zmeoR*<|EN=K+&Qhq7kSH&vZrgq=EGEew_|zg4QuWv#8VPGQCGW1nq(#8Awy?q_19D z8Li>reXws5h%SmsGszG|H+pCFMctXt)rA_Lc*@&N*C z$>2Uh%Ok;D1K~F#4Ja#n;G+#h_7L4gdNipv5ZguU0NUC<;=fO)zqHd*PM|4g5^>sx z>3W4Eaq<))4^fh)l7l#gC^Lox{h&Ig$mc3KeMgAPRFy#B5UU(lIIePB>!Q-$6Z;cQ kpFlE&js_CD;GwSw1-~QOzWlfsk}Qlsd{%a>uc__&KWVw%^#A|> diff --git a/regression/strings/java_string_builder_insert/test_insert.java b/regression/strings/java_string_builder_insert/test_insert.java deleted file mode 100644 index 1fac897c5ed..00000000000 --- a/regression/strings/java_string_builder_insert/test_insert.java +++ /dev/null @@ -1,20 +0,0 @@ -public class test_insert { - - public static void main(String[] argv) - { - char [] str = new char[5]; - str[0] = 'H'; - str[1] = 'e'; - str[2] = 'l'; - str[3] = 'l'; - str[4] = 'o'; - - - StringBuilder sb = new StringBuilder(" world"); - sb.insert(0,str); - String s = sb.toString(); - System.out.println(s); - assert(s.equals("Hello world")); - assert(!s.equals("Hello world")); - } -} diff --git a/regression/strings/java_string_builder_length/test.desc b/regression/strings/java_string_builder_length/test.desc deleted file mode 100644 index c4720992571..00000000000 --- a/regression/strings/java_string_builder_length/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -test_sb_length.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -\[assertion.1\] assertion at file test_sb_length.java line 6: SUCCESS$ -\[assertion.2\] assertion at file test_sb_length.java line 8: FAILURE$ --- diff --git a/regression/strings/java_string_builder_length/test_sb_length.class b/regression/strings/java_string_builder_length/test_sb_length.class deleted file mode 100644 index 586e8f71935b9b16a50d4a4a6ad14c4069667c5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 791 zcmZuv&rcIk5dPkFyT7`H((4HUL5zx!m=rzKNWcSm?LOV z9Ojj`VB)$1TY(lG+`vr}w-`!`JdQ<_$Zi-vmN9Py!e?N+491!aWpbY(<1M{l(AT@Z zU>I-6P(1A)v_$k=fhlpoWymn?y=?6Bx4a(kuv2d)kqkSlsxaS7c>B#3@1=NB$Y8Ct zgOlb?v)hl_VpFPCr9{NZUfkLXMA%7Quc&@53YcJ+`M39@z6^X3kXegw9BMV3A)KH=IOL~x;`tE)v)Ac zK*BLWZ;`&{$TG6o>JaR+0-{8(kp>z43X_;3UqRnfsYZ752-;3DGlbr#6|(~v+h1TF zVzM@XRj@xGcLaN92s!bMJ{(&0yQp#NU4b&{7CjbBd diff --git a/regression/strings/java_string_builder_length/test_sb_length.java b/regression/strings/java_string_builder_length/test_sb_length.java deleted file mode 100644 index 652b72cdc90..00000000000 --- a/regression/strings/java_string_builder_length/test_sb_length.java +++ /dev/null @@ -1,11 +0,0 @@ -public class test_sb_length { - public static void main(String[] argv) { - StringBuilder tmp = new StringBuilder("prefix"); - //tmp.append("prefix"); - tmp.append("end"); - assert(tmp.length() == 9); - if(argv.length > 1) { - assert(tmp.length() == 12); - } - } -} diff --git a/regression/strings/java_strlen/test.desc b/regression/strings/java_strlen/test.desc deleted file mode 100644 index b98e6f76f0a..00000000000 --- a/regression/strings/java_strlen/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -test_length.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_length.java line 10: SUCCESS$ -^\[assertion.2\] assertion at file test_length.java line 11: FAILURE$ --- diff --git a/regression/strings/java_strlen/test_length.class b/regression/strings/java_strlen/test_length.class deleted file mode 100644 index 7f1c10c02ca3c0b61fb85561752aa7e23c0b36f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 864 zcmZuvU2hUW6g{)-7t3NPNTn*;D&j)1XsbSGZEUb6O{gYfOj;kzvP@v>cGv7K{+Pb_ zV&bzJA+bq)_eWXpP$^YOcJIubIrrWcl!+6@C`+|*z(Km<~A3FT0E2?E;9>s4w?swzfvZ!YwgIU7=t<9kHxaS38ziMI$H50e6Y@&|a zCeC4op)kqW7>nEt!ysfxooS=tj)@hl{?+7pdyhLY`7=coL*AOMRXsWQ$g?f7&@<(h| z<(2K)0Lpr8X#n+sJTDgq(C#Z=pdTQcS2Dd1NF5@%GlcQu6b#OQqOmk;T&9+Q3 1) { - String t = argv[1]; - int i = t.length(); - String u = t.concat(s); - char c = u.charAt(i); - assert(c == 'h'); - assert(c == 'o'); - } - } -} diff --git a/regression/strings/java_substring/test.desc b/regression/strings/java_substring/test.desc deleted file mode 100644 index bd54a8204fe..00000000000 --- a/regression/strings/java_substring/test.desc +++ /dev/null @@ -1,10 +0,0 @@ -FUTURE -test_substring.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_substring.java line 12: SUCCESS$ -^\[assertion.2\] assertion at file test_substring.java line 13: FAILURE$ -^\[assertion.3\] assertion at file test_substring.java line 20: SUCCESS$ -^\[assertion.4\] assertion at file test_substring.java line 21: FAILURE$ --- diff --git a/regression/strings/java_substring/test_substring.class b/regression/strings/java_substring/test_substring.class deleted file mode 100644 index e6532aca43e8ec0108d5f9108ccd271907039b70..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1051 zcmbVK-%ry}7(I9EkI@wv%poEuD9U~yQxG(P5D+xZfSSyZfDfkI8Yqqq+fLv7BYfmV z5{*2o$%vZZyML5;ZjlYtCzIxDd+#~tyXSoO$Iq_^048wDfQfzs1Gpf|MOg;hU|>kc zB?H>g-sL!kF{tB;fvXtNkrqe}TfT35fm3t+MaQ>FRl6b})&#T}$8~~PfoM9jBA_hP zDz-r9lH=MB>suw;dm_Qy*s>f~peOxwY14XX<*Syvo-YQT@XW85{7_^}s+#CTftPrCe+m_d~T9)xMxDg8$T$W+I`P2Vqrsc$I1Bv=l=h ztqt;T1aV$66L*--3iDZIHWt&_pyh4yUJ?D85xhYPAIM5kbq?ww37U=`9cTFn!3YnD zj2tbo@gZ)v0KH9sAb<)noNG>CGK?DNPQqv)z5`v^gA)A=wdLS=9J0HLNc)@|T3=}J F{4e6h&lUgx diff --git a/regression/strings/java_substring/test_substring.java b/regression/strings/java_substring/test_substring.java deleted file mode 100644 index 8a2ac883cca..00000000000 --- a/regression/strings/java_substring/test_substring.java +++ /dev/null @@ -1,27 +0,0 @@ -public class test_substring { - - public static void main(String[] argv) { - if(argv.length > 1) { - String t = argv[1]; - - if(t.length() == 6) { - String u = t.substring(2,4); - char c = u.charAt(1); - char d = t.charAt(3); - char e = t.charAt(4); - assert(c == d); - assert(c == e); - } - else if(t.length() == 5){ - CharSequence u = t.subSequence(2,4); - char c = u.charAt(1); - char d = t.charAt(3); - char e = t.charAt(4); - assert(c == d); - assert(c == e); - } - - - } - } -} diff --git a/regression/strings/java_suffix/test.desc b/regression/strings/java_suffix/test.desc deleted file mode 100644 index 2740e87d6e4..00000000000 --- a/regression/strings/java_suffix/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -test_suffix.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_suffix.java line 12: SUCCESS$ -^\[assertion.2\] assertion at file test_suffix.java line 13: FAILURE$ --- diff --git a/regression/strings/java_suffix/test_suffix.class b/regression/strings/java_suffix/test_suffix.class deleted file mode 100644 index 557acd02653a0558f2ddb5117649f5cdd387e77e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 811 zcmZ`%(M}UV6g|^!JKOD+*4APbixf}`1*#H#kq`)Kd?@-*V*@^zZFj)IW!LOZjUV9` z^ap%alQxk=-~A}{&ZbZ_m~8IcJ#*&XbMDN~U*En1SjW1BDO5RTP28}Mz?_MiiFuta z=&+c9jhh^|ELfU%+d>^n9Lo%)MJI|xsAS+rk7VR@J>fF2eTMXg^rhNlNY5FImIq#jO=lF-swhE z$zX2uym5W29rVMVcp`PRf)bH>9rX_mGH=qZ}n1x^{t^^5(R z!gr&NRB!%6p;23razZsGIk%LKC7Bi%HmHxI!_Z8YL zBk`Mn6i0>QDt(Of7KwcA%*6dzEukgYL*xeF#wQrbugFYVojTGbQ%K~twC|Z%$@M>U CNTL-0 diff --git a/regression/strings/java_suffix/test_suffix.java b/regression/strings/java_suffix/test_suffix.java deleted file mode 100644 index f61b0b8ba36..00000000000 --- a/regression/strings/java_suffix/test_suffix.java +++ /dev/null @@ -1,15 +0,0 @@ -public class test_suffix { - - public static void main(String[] argv) { - String s = new String("Hello World!"); - //String t = new String("Hello"); - //String u = new String("Wello"); - String u = "Wello!"; - boolean b = s.endsWith("World!"); - //boolean c = s.startsWith("Wello"); - //boolean b = s.startsWith(t); - boolean c = s.startsWith(u); - assert(b); - assert(c); - } -} diff --git a/regression/strings/java_trim/test.desc b/regression/strings/java_trim/test.desc deleted file mode 100644 index 7c0f1a87978..00000000000 --- a/regression/strings/java_trim/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -test_trim.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_trim.java line 5: SUCCESS$ -^\[assertion.2\] assertion at file test_trim.java line 6: FAILURE$ --- diff --git a/regression/strings/java_trim/test_trim.class b/regression/strings/java_trim/test_trim.class deleted file mode 100644 index 8e6a923dcbc867d6e06db7e6b4ad880270c3084d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 730 zcmZWn%Wl&^6g}fd#&Mk{Bxwkb5*JGA^pyny7OfDdz$z_^ASB8Hjh#{D)^Vuq@G<#; zt^p~PK!QF01mccM5-MbC=FWYbd(WBq`TOg401wcy;ozo)TQ+WExdGLoZekA)0?1-VT7sg@sghBV(Zy1dIVP7(oyJ0L3 zM+09buT?Sy1|p0Z8s59^iTEfwk%*5wy(|gi<6Tu)>SZE0JrE!Ae2#SnYcGiYg4?~} zC<)}tP(dwbGR@vo>0n1eIVhvTP;_14`flJ7iFF4a+73!sWH58LgAHslH0RBqO&PsN zl3_v<3O{fOXNJzP Date: Tue, 28 Mar 2017 17:53:51 +0100 Subject: [PATCH 145/699] Display dynamic object names as 'data' in JSON traces Fixes diffblue/test-gen#147 --- src/util/json_expr.cpp | 70 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/src/util/json_expr.cpp b/src/util/json_expr.cpp index 77f58eb0e18..3b494ff9543 100644 --- a/src/util/json_expr.cpp +++ b/src/util/json_expr.cpp @@ -14,11 +14,67 @@ Author: Peter Schrammel #include "fixedbv.h" #include "std_expr.h" #include "config.h" +#include "identifier.h" #include "json_expr.h" /*******************************************************************\ +Function: simplify_json_expr + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +static exprt simplify_json_expr( + const exprt &src, + const namespacet &ns) +{ + if(src.id()==ID_constant) + { + const typet &type=ns.follow(src.type()); + + if(type.id()==ID_pointer) + { + const irep_idt &value=to_constant_expr(src).get_value(); + + if(value!=ID_NULL && + (value!=std::string(value.size(), '0') || + !config.ansi_c.NULL_is_zero) && + src.operands().size()==1 && + src.op0().id()!=ID_constant) + // try to simplify the constant pointer + return simplify_json_expr(src.op0(), ns); + } + } + else if(src.id()==ID_address_of && + src.operands().size()==1 && + src.op0().id()==ID_member && + id2string(to_member_expr( + src.op0()).get_component_name()).find("@")!=std::string::npos) + { + // simplify things of the form &member_expr(object, @class_identifier) + return simplify_json_expr(src.op0(), ns); + } + else if(src.id()==ID_member && + src.operands().size()==1 && + id2string( + to_member_expr(src).get_component_name()) + .find("@")!=std::string::npos) + { + // simplify things of the form member_expr(object, @class_identifier) + return simplify_json_expr(src.op0(), ns); + } + + return src; +} + +/*******************************************************************\ + Function: json Inputs: @@ -262,9 +318,19 @@ json_objectt json( else if(type.id()==ID_pointer) { result["name"]=json_stringt("pointer"); - result["binary"]=json_stringt(expr.get_string(ID_value)); - if(expr.get(ID_value)==ID_NULL) + exprt simpl_expr=simplify_json_expr(expr, ns); + if(simpl_expr.get(ID_value)==ID_NULL || + // remove typecast on NULL + (simpl_expr.id()==ID_constant && simpl_expr.type().id()==ID_pointer && + simpl_expr.op0().get(ID_value)==ID_NULL)) result["data"]=json_stringt("NULL"); + else if(simpl_expr.id()==ID_symbol) + { + const irep_idt &ptr_id=to_symbol_expr(simpl_expr).get_identifier(); + identifiert identifier(id2string(ptr_id)); + assert(!identifier.components.empty()); + result["data"]=json_stringt(identifier.components.back()); + } } else if(type.id()==ID_bool) { From 2e62c6638312b619d464d4b4c6a6b29f24681f36 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Thu, 30 Mar 2017 09:13:33 +0100 Subject: [PATCH 146/699] New class for sparse vectors in util Sparse vectors represent a 2^64 sized space while allocating only space that is used. --- src/util/sparse_vector.h | 60 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/util/sparse_vector.h diff --git a/src/util/sparse_vector.h b/src/util/sparse_vector.h new file mode 100644 index 00000000000..6c4e050b323 --- /dev/null +++ b/src/util/sparse_vector.h @@ -0,0 +1,60 @@ +/*******************************************************************\ + +Module: Sparse Vectors + +Author: Romain Brenguier + +\*******************************************************************/ + +#ifndef CPROVER_UTIL_SPARSE_VECTOR_H +#define CPROVER_UTIL_SPARSE_VECTOR_H + +#include + +template class sparse_vectort +{ +protected: + typedef std::map underlyingt; + underlyingt underlying; + uint64_t _size; + +public: + sparse_vectort() : + _size(0) {} + + const T &operator[](uint64_t idx) const + { + assert(idx<_size && "index out of range"); + return underlying[idx]; + } + + T &operator[](uint64_t idx) + { + assert(idx<_size && "index out of range"); + return underlying[idx]; + } + + uint64_t size() const + { + return _size; + } + + void resize(uint64_t new_size) + { + assert(new_size>=_size && "sparse vector can't be shrunk (yet)"); + _size=new_size; + } + + typedef typename underlyingt::iterator iteratort; + typedef typename underlyingt::const_iterator const_iteratort; + + iteratort begin() { return underlying.begin(); } + const_iteratort begin() const { return underlying.begin(); } + + iteratort end() { return underlying.end(); } + const_iteratort end() const { return underlying.end(); } + + const_iteratort find(uint64_t idx) { return underlying.find(idx); } +}; + +#endif // CPROVER_UTIL_SPARSE_VECTOR_H From 5d2919b36e8ddcc57ddd00770491725d234d0be2 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Thu, 23 Mar 2017 10:19:41 +0000 Subject: [PATCH 147/699] Interpreter: switch to sparse vector memory map This will allow large address reservations for unbounded-sized objects, with actual cells allocated on demand. Original patch: From: Chris Smowton Date: Tue, 21 Mar 2017 15:24:03 +0000 Subject: [PATCH 1/3] Interpreter: switch to sparse vector memory map --- src/goto-programs/interpreter.cpp | 61 +++++-------- src/goto-programs/interpreter_class.h | 70 +++++++++++++-- src/goto-programs/interpreter_evaluate.cpp | 100 ++++++++++++++++++--- 3 files changed, 176 insertions(+), 55 deletions(-) diff --git a/src/goto-programs/interpreter.cpp b/src/goto-programs/interpreter.cpp index 8d1565db914..555c50ff0d0 100644 --- a/src/goto-programs/interpreter.cpp +++ b/src/goto-programs/interpreter.cpp @@ -712,22 +712,24 @@ exprt interpretert::get_value( if(rhs[offset]0) offset++; - + std::size_t address=memory_map[id]; + std::size_t current_size=base_address_to_alloc_size(address); // current size <= size already recorded - if(size<=offset) + if(size<=current_size) return memory_map[id]; } @@ -1151,19 +1143,12 @@ mp_integer interpretert::build_memory_map( if(size==0) size=1; // This is a hack to create existence - unsigned address=memory.size(); + std::size_t address=memory.size(); memory.resize(address+size); memory_map[id]=address; + inverse_memory_map[address]=id; dynamic_types.insert(std::pair(id, alloc_type)); - for(size_t i=0; i #include +#include #include "goto_functions.h" #include "goto_trace.h" @@ -68,6 +69,9 @@ class interpretert:public messaget // List of dynamically allocated symbols that are not in the symbol table typedef std::map dynamic_typest; + typedef std::map output_valuest; + output_valuest output_values; + // An assignment list annotated with the calling context. struct function_assignments_contextt { @@ -103,27 +107,78 @@ class interpretert:public messaget const goto_functionst &goto_functions; - typedef std::unordered_map memory_mapt; + typedef std::unordered_map memory_mapt; + typedef std::map inverse_memory_mapt; memory_mapt memory_map; + inverse_memory_mapt inverse_memory_map; + + const inverse_memory_mapt::value_type &address_to_object_record( + std::size_t address) const + { + auto lower_bound=inverse_memory_map.lower_bound(address); + if(lower_bound->first!=address) + { + assert(lower_bound!=inverse_memory_map.begin()); + --lower_bound; + } + return *lower_bound; + } + + irep_idt address_to_identifier(std::size_t address) const + { + return address_to_object_record(address).second; + } + + std::size_t address_to_offset(std::size_t address) const + { + return address-(address_to_object_record(address).first); + } + + std::size_t base_address_to_alloc_size(std::size_t address) const + { + assert(address_to_offset(address)==0); + auto upper_bound=inverse_memory_map.upper_bound(address); + std::size_t next_alloc_address= + upper_bound==inverse_memory_map.end() ? + memory.size() : + upper_bound->first; + return next_alloc_address-address; + } + + std::size_t base_address_to_actual_size(std::size_t address) const + { + auto memory_iter=memory.find(address); + if(memory_iter==memory.end()) + return 0; + std::size_t ret=0; + std::size_t alloc_size=base_address_to_alloc_size(address); + while(memory_iter!=memory.end() && ret memoryt; + typedef sparse_vectort memoryt; typedef std::map parameter_sett; // mapping -> value typedef std::pair struct_member_idt; typedef std::map struct_valuest; - // The memory is being annotated/reshaped even during reads // (ie to find a read-before-write location) thus memory // properties need to be mutable to avoid making all calls nonconst @@ -135,6 +190,7 @@ class interpretert:public messaget void build_memory_map(const symbolt &symbol); mp_integer build_memory_map(const irep_idt &id, const typet &type); typet concretize_type(const typet &type); + bool unbounded_size(const typet &); size_t get_size(const typet &type); irep_idt get_component_id(const irep_idt &object, unsigned offset); @@ -169,6 +225,10 @@ class interpretert:public messaget mp_integer address, mp_vectort &dest) const; + void read_unbounded( + mp_integer address, + mp_vectort &dest) const; + virtual void command(); class stack_framet diff --git a/src/goto-programs/interpreter_evaluate.cpp b/src/goto-programs/interpreter_evaluate.cpp index 712d4b9d807..f285328aedd 100644 --- a/src/goto-programs/interpreter_evaluate.cpp +++ b/src/goto-programs/interpreter_evaluate.cpp @@ -54,6 +54,34 @@ void interpretert::read( } } +void interpretert::read_unbounded( + mp_integer address, + mp_vectort &dest) const +{ + // copy memory region + std::size_t address_val=integer2size_t(address); + const std::size_t offset=address_to_offset(address_val); + const std::size_t alloc_size= + base_address_to_actual_size(address_val-offset); + const std::size_t to_read=alloc_size-offset; + for(size_t i=0; i0) - cell.initialized=0; + if(cell.second.initialized>0) + cell.second.initialized=0; } } @@ -441,7 +469,8 @@ void interpretert::evaluate( } else if(expr.id()==ID_struct) { - dest.reserve(get_size(expr.type())); + if(!unbounded_size(expr.type())) + dest.reserve(get_size(expr.type())); bool error=false; forall_operands(it, expr) @@ -456,9 +485,9 @@ void interpretert::evaluate( mp_vectort tmp; evaluate(*it, tmp); - if(tmp.size()==sub_size) + if(unbounded_size(it->type()) || tmp.size()==sub_size) { - for(size_t i=0; i0 && address size; + if(ty.size().id()==ID_infinity) + size.push_back(0); + else + evaluate(ty.size(), size); + if(size.size()==1) + { + std::size_t size_int=integer2size_t(size[0]); + for(std::size_t i=0; i where; + std::vector new_value; + evaluate(wexpr.where(), where); + evaluate(wexpr.new_value(), new_value); + const auto &subtype=expr.type().subtype(); + if(!new_value.empty() && where.size()==1 && !unbounded_size(subtype)) + { + // Ignore indices < 0, which the string solver sometimes produces + if(where[0]<0) + return; + std::size_t where_idx=integer2size_t(where[0]); + std::size_t subtype_size=get_size(subtype); + std::size_t need_size=(where_idx+1)*subtype_size; + if(dest.size() Date: Thu, 23 Mar 2017 11:15:30 +0000 Subject: [PATCH 148/699] Add support for unbounded-size objects They get allocated 2^32 address space each (of a 2^64 sized space) using the sparse-vector memory representation to keep the actual storage requirements sensible. Original patch: From: Chris Smowton Date: Tue, 21 Mar 2017 17:13:43 +0000 Subject: [PATCH 2/3] Add support for unbounded-size objects Corrected linting issues Using empty, and comments on get_size --- src/goto-programs/interpreter.cpp | 77 +++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 15 deletions(-) diff --git a/src/goto-programs/interpreter.cpp b/src/goto-programs/interpreter.cpp index 555c50ff0d0..ff61e53b615 100644 --- a/src/goto-programs/interpreter.cpp +++ b/src/goto-programs/interpreter.cpp @@ -597,16 +597,25 @@ exprt interpretert::get_value( exprt result=array_exprt(to_array_type(real_type)); const exprt &size_expr=static_cast(type.find(ID_size)); size_t subtype_size=get_size(type.subtype()); - mp_integer mp_count; - to_integer(size_expr, mp_count); - unsigned count=integer2unsigned(mp_count); + std::size_t count; + if(size_expr.id()!=ID_constant) + { + count=base_address_to_actual_size(offset)/subtype_size; + } + else + { + mp_integer mp_count; + to_integer(size_expr, mp_count); + count=integer2size_t(mp_count); + } // Retrieve the value for each member in the array result.reserve_operands(count); for(unsigned i=0; i(cell.initialized) << ")" From a5f773923a7a9ae3c294e0258fada17f8c5de5a6 Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Mon, 6 Mar 2017 09:46:38 +0000 Subject: [PATCH 149/699] set internal for specific variables in the counterexample trace for test-gen-support set internal for variable assignments related to dynamic_object[0-9], dynamic_[0-9]_array, _start function-return step, and CPROVER internal functions (e.g., __CPROVER_initialize). This PR fixes diffblue/test-gen#20. --- src/goto-symex/build_goto_trace.cpp | 82 +++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/src/goto-symex/build_goto_trace.cpp b/src/goto-symex/build_goto_trace.cpp index 0e0a6f07dad..1221154d6a3 100644 --- a/src/goto-symex/build_goto_trace.cpp +++ b/src/goto-symex/build_goto_trace.cpp @@ -132,6 +132,85 @@ exprt adjust_lhs_object( /*******************************************************************\ +Function: hide_dynamic_object + + Inputs: + + Outputs: + + Purpose: hide variable assignments related to dynamic_object[0-9] + and dynamic_[0-9]_array. + +\*******************************************************************/ + +void hide_dynamic_object( + const exprt &expr, + goto_trace_stept &goto_trace_step, + const namespacet &ns) +{ + if(expr.id()==ID_symbol) + { + const irep_idt &id=to_ssa_expr(expr).get_original_name(); + const symbolt *symbol; + if(!ns.lookup(id, symbol)) + { + bool result=symbol->type.get_bool("#dynamic"); + if(result) + goto_trace_step.hidden=true; + } + } + else + { + forall_operands(it, expr) + hide_dynamic_object(*it, goto_trace_step, ns); + } +} + +/*******************************************************************\ + +Function: update_fields_to_hidden + + Inputs: + + Outputs: + + Purpose: hide variables assignments related to dynamic_object + and CPROVER internal functions (e.g., __CPROVER_initialize) + +\*******************************************************************/ + +void update_fields_to_hidden( + const symex_target_equationt::SSA_stept &SSA_step, + goto_trace_stept &goto_trace_step, + const namespacet &ns) +{ + // hide dynamic_object in both lhs and rhs expressions + hide_dynamic_object(SSA_step.ssa_lhs, goto_trace_step, ns); + hide_dynamic_object(SSA_step.ssa_rhs, goto_trace_step, ns); + + // hide internal CPROVER functions (e.g., __CPROVER_initialize) + if(SSA_step.is_function_call()) + { + if(SSA_step.source.pc->source_location.as_string().empty()) + goto_trace_step.hidden=true; + } + + // hide input and output steps + if(goto_trace_step.type==goto_trace_stept::OUTPUT || + goto_trace_step.type==goto_trace_stept::INPUT) + { + goto_trace_step.hidden=true; + } + + // set internal field to _start function-return step + if(SSA_step.source.pc->function==goto_functionst::entry_point()) + { + goto_trace_step.internal=true; + } +} + +/*******************************************************************\ + Function: build_goto_trace Inputs: @@ -237,6 +316,9 @@ void build_goto_trace( goto_trace_step.formatted=SSA_step.formatted; goto_trace_step.identifier=SSA_step.identifier; + // hide specific variables in the counterexample trace + update_fields_to_hidden(SSA_step, goto_trace_step, ns); + goto_trace_step.assignment_type= (it->is_assignment()&& (SSA_step.assignment_type==symex_targett::VISIBLE_ACTUAL_PARAMETER || From 508131009310a717346ea40c1402d60e73fe8b18 Mon Sep 17 00:00:00 2001 From: Lucas Cordeiro Date: Tue, 28 Mar 2017 16:00:35 +0100 Subject: [PATCH 150/699] added internal field to json output Added internal field to json output so that we set it to tru as we find some specific variable that is not supposed to be shown in the counterexample trace. --- src/goto-programs/goto_trace.h | 4 +++ src/goto-programs/json_goto_trace.cpp | 6 +++++ src/goto-symex/build_goto_trace.cpp | 39 ++++++++++++++------------- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/goto-programs/goto_trace.h b/src/goto-programs/goto_trace.h index a669fac5e6b..dc270863894 100644 --- a/src/goto-programs/goto_trace.h +++ b/src/goto-programs/goto_trace.h @@ -63,6 +63,9 @@ class goto_trace_stept // we may choose to hide a step bool hidden; + // this is related to an internal expression + bool internal; + // we categorize typedef enum { STATE, ACTUAL_PARAMETER } assignment_typet; assignment_typet assignment_type; @@ -107,6 +110,7 @@ class goto_trace_stept step_nr(0), type(NONE), hidden(false), + internal(false), assignment_type(STATE), thread_nr(0), cond_value(false), diff --git a/src/goto-programs/json_goto_trace.cpp b/src/goto-programs/json_goto_trace.cpp index da6590fe2de..3dca95bc93b 100644 --- a/src/goto-programs/json_goto_trace.cpp +++ b/src/goto-programs/json_goto_trace.cpp @@ -68,6 +68,7 @@ void convert( json_failure["stepType"]=json_stringt("failure"); json_failure["hidden"]=jsont::json_boolean(step.hidden); + json_failure["internal"]=jsont::json_boolean(step.internal); json_failure["thread"]=json_numbert(std::to_string(step.thread_nr)); json_failure["reason"]=json_stringt(id2string(step.comment)); json_failure["property"]=json_stringt(id2string(property_id)); @@ -118,6 +119,7 @@ void convert( json_assignment["value"]=full_lhs_value; json_assignment["lhs"]=json_stringt(full_lhs_string); json_assignment["hidden"]=jsont::json_boolean(step.hidden); + json_assignment["internal"]=jsont::json_boolean(step.internal); json_assignment["thread"]=json_numbert(std::to_string(step.thread_nr)); json_assignment["assignmentType"]= @@ -132,6 +134,7 @@ void convert( json_output["stepType"]=json_stringt("output"); json_output["hidden"]=jsont::json_boolean(step.hidden); + json_output["internal"]=jsont::json_boolean(step.internal); json_output["thread"]=json_numbert(std::to_string(step.thread_nr)); json_output["outputID"]=json_stringt(id2string(step.io_id)); @@ -156,6 +159,7 @@ void convert( json_input["stepType"]=json_stringt("input"); json_input["hidden"]=jsont::json_boolean(step.hidden); + json_input["internal"]=jsont::json_boolean(step.internal); json_input["thread"]=json_numbert(std::to_string(step.thread_nr)); json_input["inputID"]=json_stringt(id2string(step.io_id)); @@ -184,6 +188,7 @@ void convert( json_call_return["stepType"]=json_stringt(tag); json_call_return["hidden"]=jsont::json_boolean(step.hidden); + json_call_return["internal"]=jsont::json_boolean(step.internal); json_call_return["thread"]=json_numbert(std::to_string(step.thread_nr)); const symbolt &symbol=ns.lookup(step.identifier); @@ -207,6 +212,7 @@ void convert( json_objectt &json_location_only=dest_array.push_back().make_object(); json_location_only["stepType"]=json_stringt("location-only"); json_location_only["hidden"]=jsont::json_boolean(step.hidden); + json_location_only["internal"]=jsont::json_boolean(step.internal); json_location_only["thread"]= json_numbert(std::to_string(step.thread_nr)); json_location_only["sourceLocation"]=json_location; diff --git a/src/goto-symex/build_goto_trace.cpp b/src/goto-symex/build_goto_trace.cpp index 1221154d6a3..1cbb442497a 100644 --- a/src/goto-symex/build_goto_trace.cpp +++ b/src/goto-symex/build_goto_trace.cpp @@ -132,18 +132,18 @@ exprt adjust_lhs_object( /*******************************************************************\ -Function: hide_dynamic_object +Function: set_internal_dynamic_object Inputs: Outputs: - Purpose: hide variable assignments related to dynamic_object[0-9] - and dynamic_[0-9]_array. + Purpose: set internal field for variable assignment related to + dynamic_object[0-9] and dynamic_[0-9]_array. \*******************************************************************/ -void hide_dynamic_object( +void set_internal_dynamic_object( const exprt &expr, goto_trace_stept &goto_trace_step, const namespacet &ns) @@ -156,50 +156,51 @@ void hide_dynamic_object( { bool result=symbol->type.get_bool("#dynamic"); if(result) - goto_trace_step.hidden=true; + goto_trace_step.internal=true; } } else { forall_operands(it, expr) - hide_dynamic_object(*it, goto_trace_step, ns); + set_internal_dynamic_object(*it, goto_trace_step, ns); } } /*******************************************************************\ -Function: update_fields_to_hidden +Function: update_internal_field Inputs: Outputs: - Purpose: hide variables assignments related to dynamic_object - and CPROVER internal functions (e.g., __CPROVER_initialize) + Purpose: set internal for variables assignments related to + dynamic_object and CPROVER internal functions + (e.g., __CPROVER_initialize) \*******************************************************************/ -void update_fields_to_hidden( +void update_internal_field( const symex_target_equationt::SSA_stept &SSA_step, goto_trace_stept &goto_trace_step, const namespacet &ns) { - // hide dynamic_object in both lhs and rhs expressions - hide_dynamic_object(SSA_step.ssa_lhs, goto_trace_step, ns); - hide_dynamic_object(SSA_step.ssa_rhs, goto_trace_step, ns); + // set internal for dynamic_object in both lhs and rhs expressions + set_internal_dynamic_object(SSA_step.ssa_lhs, goto_trace_step, ns); + set_internal_dynamic_object(SSA_step.ssa_rhs, goto_trace_step, ns); - // hide internal CPROVER functions (e.g., __CPROVER_initialize) + // set internal field to CPROVER functions (e.g., __CPROVER_initialize) if(SSA_step.is_function_call()) { if(SSA_step.source.pc->source_location.as_string().empty()) - goto_trace_step.hidden=true; + goto_trace_step.internal=true; } - // hide input and output steps + // set internal field to input and output steps if(goto_trace_step.type==goto_trace_stept::OUTPUT || goto_trace_step.type==goto_trace_stept::INPUT) { - goto_trace_step.hidden=true; + goto_trace_step.internal=true; } // set internal field to _start function-return step @@ -316,8 +317,8 @@ void build_goto_trace( goto_trace_step.formatted=SSA_step.formatted; goto_trace_step.identifier=SSA_step.identifier; - // hide specific variables in the counterexample trace - update_fields_to_hidden(SSA_step, goto_trace_step, ns); + // update internal field for specific variables in the counterexample + update_internal_field(SSA_step, goto_trace_step, ns); goto_trace_step.assignment_type= (it->is_assignment()&& From 9ddfb302aa9eef8bc3597a6deefbd5d0103e5905 Mon Sep 17 00:00:00 2001 From: Joel Allred Date: Fri, 31 Mar 2017 14:02:16 +0100 Subject: [PATCH 151/699] Add includes to sparse_vector.h Fixes a build issue with testgen --- src/util/sparse_vector.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/util/sparse_vector.h b/src/util/sparse_vector.h index 6c4e050b323..193e9a68a01 100644 --- a/src/util/sparse_vector.h +++ b/src/util/sparse_vector.h @@ -9,7 +9,9 @@ Author: Romain Brenguier #ifndef CPROVER_UTIL_SPARSE_VECTOR_H #define CPROVER_UTIL_SPARSE_VECTOR_H -#include +#include +#include +#include template class sparse_vectort { From 6c1f70074bdb7754d35ca5164c24c0469e82e5e4 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Fri, 17 Mar 2017 13:08:37 +0000 Subject: [PATCH 152/699] Adding options to cbmc for parameters of the string solver We add the options string-max-length, string-non-empty, and string-printable --- src/cbmc/cbmc_parse_options.cpp | 8 ++++++++ src/cbmc/cbmc_parse_options.h | 2 +- src/cbmc/cbmc_solvers.cpp | 10 ++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/cbmc/cbmc_parse_options.cpp b/src/cbmc/cbmc_parse_options.cpp index 1f49653c644..5af90c00b79 100644 --- a/src/cbmc/cbmc_parse_options.cpp +++ b/src/cbmc/cbmc_parse_options.cpp @@ -320,6 +320,11 @@ void cbmc_parse_optionst::get_command_line_options(optionst &options) if(cmdline.isset("refine-strings")) { options.set_option("refine-strings", true); + options.set_option("string-non-empty", cmdline.isset("string-non-empty")); + options.set_option("string-printable", cmdline.isset("string-printable")); + if(cmdline.isset("string-max-length")) + options.set_option( + "string-max-length", cmdline.get_value("string-max-length")); } if(cmdline.isset("max-node-refinement")) @@ -1207,6 +1212,9 @@ void cbmc_parse_optionst::help() " --z3 use Z3\n" " --refine use refinement procedure (experimental)\n" " --refine-strings use string refinement (experimental)\n" + " --string-non-empty add constraint that strings are non empty (experimental)\n" // NOLINT(*) + " --string-printable add constraint that strings are printable (experimental)\n" // NOLINT(*) + " --string-max-length add constraint on the length of strings (experimental)\n" // NOLINT(*) " --outfile filename output formula to given file\n" " --arrays-uf-never never turn arrays into uninterpreted functions\n" // NOLINT(*) " --arrays-uf-always always turn arrays into uninterpreted functions\n" // NOLINT(*) diff --git a/src/cbmc/cbmc_parse_options.h b/src/cbmc/cbmc_parse_options.h index b3225951b3b..4bdc07a6278 100644 --- a/src/cbmc/cbmc_parse_options.h +++ b/src/cbmc/cbmc_parse_options.h @@ -38,7 +38,7 @@ class optionst; "(no-sat-preprocessor)" \ "(no-pretty-names)(beautify)" \ "(dimacs)(refine)(max-node-refinement):(refine-arrays)(refine-arithmetic)"\ - "(refine-strings)" \ + "(refine-strings)(string-non-empty)(string-printable)(string-max-length):" \ "(aig)(16)(32)(64)(LP64)(ILP64)(LLP64)(ILP32)(LP32)" \ "(little-endian)(big-endian)" \ "(show-goto-functions)(show-loops)" \ diff --git a/src/cbmc/cbmc_solvers.cpp b/src/cbmc/cbmc_solvers.cpp index a72546a8d0c..dace046cc17 100644 --- a/src/cbmc/cbmc_solvers.cpp +++ b/src/cbmc/cbmc_solvers.cpp @@ -232,6 +232,16 @@ cbmc_solverst::solvert* cbmc_solverst::get_string_refinement() string_refinementt *string_refinement=new string_refinementt( ns, *prop, MAX_NB_REFINEMENT); string_refinement->set_ui(ui); + + string_refinement->do_concretizing=options.get_bool_option("trace"); + if(options.get_bool_option("string-max-length")) + string_refinement->set_max_string_length( + options.get_signed_int_option("string-max-length")); + if(options.get_bool_option("string-non-empty")) + string_refinement->enforce_non_empty_string(); + if(options.get_bool_option("string-printable")) + string_refinement->enforce_printable_characters(); + return new solvert(string_refinement, prop); } From d5c6ac636f5416bbe1a9bb8095772d6b65e6ecc1 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Fri, 17 Mar 2017 12:59:51 +0000 Subject: [PATCH 153/699] Added option to the string solver for string length and printability Added field in string_refinement and string_constraint_generator to bound size of strings in the program and enforce a range on the characters. --- .../refinement/string_constraint_generator.h | 13 +- .../string_constraint_generator_concat.cpp | 3 +- .../string_constraint_generator_main.cpp | 56 +++++-- src/solvers/refinement/string_refinement.cpp | 144 ++++++++++++++---- src/solvers/refinement/string_refinement.h | 14 +- 5 files changed, 184 insertions(+), 46 deletions(-) diff --git a/src/solvers/refinement/string_constraint_generator.h b/src/solvers/refinement/string_constraint_generator.h index 12447e0cf04..d8f3f17326e 100644 --- a/src/solvers/refinement/string_constraint_generator.h +++ b/src/solvers/refinement/string_constraint_generator.h @@ -26,9 +26,17 @@ class string_constraint_generatort // to the axiom list. string_constraint_generatort(): - mode(ID_unknown) + mode(ID_unknown), + max_string_length(-1), + force_printable_characters(false) { } + // Constraints on the maximal length of strings + int max_string_length; + + // Should we add constraints on the characters + bool force_printable_characters; + void set_mode(irep_idt _mode) { // only C and java modes supported @@ -74,6 +82,8 @@ class string_constraint_generatort // Maps unresolved symbols to the string_exprt that was created for them std::map unresolved_symbols; + // Set of strings that have been created by the generator + std::set created_strings; string_exprt find_or_add_string_of_symbol( const symbol_exprt &sym, @@ -100,6 +110,7 @@ class string_constraint_generatort static irep_idt extract_java_string(const symbol_exprt &s); + void add_default_axioms(const string_exprt &s); exprt axiom_for_is_positive_index(const exprt &x); // The following functions add axioms for the returned value diff --git a/src/solvers/refinement/string_constraint_generator_concat.cpp b/src/solvers/refinement/string_constraint_generator_concat.cpp index fb8e24d5320..eb841cc5b04 100644 --- a/src/solvers/refinement/string_constraint_generator_concat.cpp +++ b/src/solvers/refinement/string_constraint_generator_concat.cpp @@ -35,7 +35,8 @@ string_exprt string_constraint_generatort::add_axioms_for_concat( // a4 : forall i<|s1|. res[i]=s1[i] // a5 : forall i<|s2|. res[i+|s1|]=s2[i] - res.length()=plus_exprt_with_overflow_check(s1.length(), s2.length()); + equal_exprt a1(res.length(), plus_exprt_with_overflow_check(s1.length(), s2.length())); + axioms.push_back(a1); axioms.push_back(s1.axiom_for_is_shorter_than(res)); axioms.push_back(s2.axiom_for_is_shorter_than(res)); diff --git a/src/solvers/refinement/string_constraint_generator_main.cpp b/src/solvers/refinement/string_constraint_generator_main.cpp index e4292da542b..f081ac26f47 100644 --- a/src/solvers/refinement/string_constraint_generator_main.cpp +++ b/src/solvers/refinement/string_constraint_generator_main.cpp @@ -173,10 +173,11 @@ Function: string_constraint_generatort::fresh_string string_exprt string_constraint_generatort::fresh_string( const refined_string_typet &type) { - symbol_exprt length= - fresh_symbol("string_length", type.get_index_type()); + symbol_exprt length=fresh_symbol("string_length", type.get_index_type()); symbol_exprt content=fresh_symbol("string_content", type.get_content_type()); - return string_exprt(length, content, type); + string_exprt str(length, content, type); + created_strings.insert(str); + return str; } /*******************************************************************\ @@ -246,6 +247,45 @@ string_exprt string_constraint_generatort::convert_java_string_to_string_exprt( /*******************************************************************\ +Function: string_constraint_generatort::add_default_constraints + + Inputs: + s - a string expression + + Outputs: a string expression that is linked to the argument through + axioms that are added to the list + + Purpose: adds standard axioms about the length of the string and + its content: + * its length should be positive + * it should not exceed max_string_length + * if force_printable_characters is true then all characters + should belong to the range of ASCII characters between ' ' and '~' + + +\*******************************************************************/ + +void string_constraint_generatort::add_default_axioms( + const string_exprt &s) +{ + s.axiom_for_is_longer_than(from_integer(0, s.length().type())); + if(max_string_length>=0) + axioms.push_back(s.axiom_for_is_shorter_than(max_string_length)); + + if(force_printable_characters) + { + symbol_exprt qvar=fresh_univ_index("printable", s.length().type()); + exprt chr=s[qvar]; + and_exprt printable( + binary_relation_exprt(chr, ID_ge, from_integer(' ', chr.type())), + binary_relation_exprt(chr, ID_le, from_integer('~', chr.type()))); + string_constraintt sc(qvar, s.length(), printable); + axioms.push_back(sc); + } +} + +/*******************************************************************\ + Function: string_constraint_generatort::add_axioms_for_refined_string Inputs: an expression of refined string type @@ -258,7 +298,6 @@ Function: string_constraint_generatort::add_axioms_for_refined_string \*******************************************************************/ - string_exprt string_constraint_generatort::add_axioms_for_refined_string( const exprt &string) { @@ -272,15 +311,13 @@ string_exprt string_constraint_generatort::add_axioms_for_refined_string( { const symbol_exprt &sym=to_symbol_expr(string); string_exprt s=find_or_add_string_of_symbol(sym, type); - axioms.push_back( - s.axiom_for_is_longer_than(from_integer(0, s.length().type()))); + add_default_axioms(s); return s; } else if(string.id()==ID_nondet_symbol) { string_exprt s=fresh_string(type); - axioms.push_back( - s.axiom_for_is_longer_than(from_integer(0, s.length().type()))); + add_default_axioms(s); return s; } else if(string.id()==ID_if) @@ -290,8 +327,7 @@ string_exprt string_constraint_generatort::add_axioms_for_refined_string( else if(string.id()==ID_struct) { const string_exprt &s=to_string_expr(string); - axioms.push_back( - s.axiom_for_is_longer_than(from_integer(0, s.length().type()))); + add_default_axioms(s); return s; } else diff --git a/src/solvers/refinement/string_refinement.cpp b/src/solvers/refinement/string_refinement.cpp index 1391ffd2315..9d2e5627071 100644 --- a/src/solvers/refinement/string_refinement.cpp +++ b/src/solvers/refinement/string_refinement.cpp @@ -43,7 +43,8 @@ string_refinementt::string_refinementt( supert(_ns, _prop), use_counter_example(false), do_concretizing(false), - initial_loop_bound(refinement_bound) + initial_loop_bound(refinement_bound), + non_empty_string(false) { } /*******************************************************************\ @@ -65,6 +66,52 @@ void string_refinementt::set_mode() /*******************************************************************\ +Function: string_refinementt::set_max_string_length + + Inputs: + i - maximum length which is allowed for strings. + negative number means no limit + + Purpose: Add constraints on the size of strings used in the + program. + +\*******************************************************************/ + +void string_refinementt::set_max_string_length(int i) +{ + generator.max_string_length=i; +} + +/*******************************************************************\ + +Function: string_refinementt::set_max_string_length + + Purpose: Add constraints on the size of nondet character arrays + to ensure they have length at least 1 + +\*******************************************************************/ + +void string_refinementt::enforce_non_empty_string() +{ + non_empty_string=true; +} + +/*******************************************************************\ + +Function: string_refinementt::enforce_printable_characters + + Purpose: Add constraints on characters used in the program + to ensure they are printable + +\*******************************************************************/ + +void string_refinementt::enforce_printable_characters() +{ + generator.force_printable_characters=true; +} + +/*******************************************************************\ + Function: string_refinementt::display_index_set Purpose: display the current index set, for debugging @@ -283,52 +330,71 @@ bool string_refinementt::add_axioms_for_string_assigns(const exprt &lhs, /*******************************************************************\ -Function: string_refinementt::concretize_results +Function: string_refinementt::concretize_string - Purpose: For each string whose length has been solved, add constants + Input: + expr - an expression + + Purpose: If the expression is of type string, then adds constants to the index set to force the solver to pick concrete values for each character, and fill the map `found_length` \*******************************************************************/ -void string_refinementt::concretize_results() +void string_refinementt::concretize_string(const exprt &expr) { - for(const auto& it : symbol_resolve) + if(refined_string_typet::is_refined_string_type(expr.type())) { - if(refined_string_typet::is_refined_string_type(it.second.type())) + string_exprt str=to_string_expr(expr); + exprt length=get(str.length()); + add_lemma(equal_exprt(str.length(), length)); + exprt content=str.content(); + replace_expr(symbol_resolve, content); + found_length[content]=length; + mp_integer found_length; + if(!to_integer(length, found_length)) { - string_exprt str=to_string_expr(it.second); - exprt length=current_model[str.length()]; - exprt content=str.content(); - replace_expr(symbol_resolve, content); - found_length[content]=length; - mp_integer found_length; - if(!to_integer(length, found_length)) + assert(found_length.is_long()); + if(found_length < 0) { - assert(found_length.is_long()); - if(found_length < 0) - { - debug() << "concretize_results: WARNING found length is negative" - << eom; - } - else + debug() << "concretize_results: WARNING found length is negative" + << eom; + } + else + { + size_t concretize_limit=found_length.to_long(); + concretize_limit=concretize_limit>MAX_CONCRETE_STRING_SIZE? + MAX_CONCRETE_STRING_SIZE:concretize_limit; + exprt content_expr=str.content(); + for(size_t i=0; iMAX_CONCRETE_STRING_SIZE? - MAX_CONCRETE_STRING_SIZE:concretize_limit; - exprt content_expr=str.content(); - replace_expr(current_model, content_expr); - for(size_t i=0; i found_length; From 4c4d85ca67640d33986ca8b7751add917be8ccf7 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 3 Feb 2017 09:44:44 +0000 Subject: [PATCH 154/699] Implement function-only coverage This adds support for this-function-only coverage instrumentation. Some function renaming and interface improvement happens at the same time, in particular altering how no-trivial-tests is applied. Adapted from merge commit e7061a0208cde20ec1fe5b582594532e01ce11ab and subsequent fixup d462a7076f2d46bcc1bcee6e70186c76de5e36a8 which appear to have introduced this reworking as part of a merge. Original commit message was "consolidate integration with cover", committed by @cristina-david --- src/goto-instrument/cover.cpp | 247 +++++++++++++++++----------------- src/goto-instrument/cover.h | 24 +++- 2 files changed, 142 insertions(+), 129 deletions(-) diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index 0d6c2eb3539..ed40ce89f0b 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -16,6 +16,7 @@ Date: May 2016 #include #include #include +#include #include @@ -101,23 +102,6 @@ class basic_blockst /*******************************************************************\ -Function: coverage_goalst::coverage_goalst - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -coverage_goalst::coverage_goalst() -{ - no_trivial_tests=false; -} - -/*******************************************************************\ - Function: coverage_goalst::get_coverage Inputs: @@ -134,7 +118,6 @@ coverage_goalst coverage_goalst::get_coverage_goals(const std::string &coverage, jsont json; coverage_goalst goals; source_locationt source_location; - goals.set_no_trivial_tests(false); // check coverage file if(parse_json(coverage, message_handler, json)) @@ -177,7 +160,7 @@ coverage_goalst coverage_goalst::get_coverage_goals(const std::string &coverage, // get the line of each existing goal line=entry["number"].value; source_location.set_line(line); - goals.set_goals(source_location); + goals.add_goal(source_location); } } } @@ -186,7 +169,7 @@ coverage_goalst coverage_goalst::get_coverage_goals(const std::string &coverage, /*******************************************************************\ -Function: coverage_goalst::set_goals +Function: coverage_goalst::add_goal Inputs: @@ -196,7 +179,7 @@ Function: coverage_goalst::set_goals \*******************************************************************/ -void coverage_goalst::set_goals(source_locationt goal) +void coverage_goalst::add_goal(source_locationt goal) { existing_goals.push_back(goal); } @@ -213,9 +196,9 @@ Function: coverage_goalst::is_existing_goal \*******************************************************************/ -bool coverage_goalst::is_existing_goal(source_locationt source_location) +bool coverage_goalst::is_existing_goal(source_locationt source_location) const { - std::vector::iterator it = existing_goals.begin(); + std::vector::const_iterator it = existing_goals.begin(); while(it!=existing_goals.end()) { if(!source_location.get_file().compare(it->get_file()) && @@ -232,40 +215,6 @@ bool coverage_goalst::is_existing_goal(source_locationt source_location) /*******************************************************************\ -Function: coverage_goalst::set_no_trivial_tests - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void coverage_goalst::set_no_trivial_tests(const bool trivial) -{ - no_trivial_tests=trivial; -} - -/*******************************************************************\ - -Function: coverage_goalst::get_no_trivial_tests - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -const bool coverage_goalst::get_no_trivial_tests() -{ - return no_trivial_tests; -} - -/*******************************************************************\ - Function: as_string Inputs: @@ -1277,8 +1226,74 @@ void instrument_cover_goals( const symbol_tablet &symbol_table, goto_programt &goto_program, coverage_criteriont criterion, - coverage_goalst &goals) + bool function_only) +{ + coverage_goalst goals; //empty already covered goals + instrument_cover_goals(symbol_table,goto_program, + criterion,goals,function_only,false); +} + +/*******************************************************************\ + +Function: consider_goals + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool consider_goals(const goto_programt &goto_program) +{ + bool result; + unsigned long count_assignments=0, count_goto=0, count_decl=0; + + forall_goto_program_instructions(i_it, goto_program) + { + if(i_it->is_goto()) + ++count_goto; + else if (i_it->is_assign()) + ++count_assignments; + else if (i_it->is_decl()) + ++count_decl; + } + + //check whether this is a constructor/destructor or a get/set (pattern) + if (!count_goto && !count_assignments && !count_decl) + result=false; + else + result = !((count_decl==0) && (count_goto<=1) && + (count_assignments>0 && count_assignments<5)); + + return result; +} + +/*******************************************************************\ + +Function: instrument_cover_goals + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void instrument_cover_goals( + const symbol_tablet &symbol_table, + goto_programt &goto_program, + coverage_criteriont criterion, + const coverage_goalst &goals, + bool function_only, + bool ignore_trivial) { + //exclude trivial coverage goals of a goto program + if(ignore_trivial && !consider_goals(goto_program)) + return; + const namespacet ns(symbol_table); basic_blockst basic_blocks(goto_program); std::set blocks_done; @@ -1293,21 +1308,30 @@ void instrument_cover_goals( Forall_goto_program_instructions(i_it, goto_program) { + std::string curr_function = id2string(i_it->function); + + // if the --cover-function-only flag is set, then we only add coverage + // instrumentation for the entry function + bool cover_curr_function= + !function_only || + curr_function.find(config.main)!=std::string::npos; + switch(criterion) { case coverage_criteriont::ASSERTION: // turn into 'assert(false)' to avoid simplification - if(i_it->is_assert()) + if(i_it->is_assert() && cover_curr_function) { i_it->guard=false_exprt(); i_it->source_location.set(ID_coverage_criterion, coverage_criterion); i_it->source_location.set_property_class(property_class); + i_it->source_location.set_function(i_it->function); } break; case coverage_criteriont::COVER: // turn __CPROVER_cover(x) into 'assert(!x)' - if(i_it->is_function_call()) + if(i_it->is_function_call() && cover_curr_function) { const code_function_callt &code_function_call= to_code_function_call(i_it->code); @@ -1324,6 +1348,7 @@ void instrument_cover_goals( i_it->source_location.set_comment(comment); i_it->source_location.set(ID_coverage_criterion, coverage_criterion); i_it->source_location.set_property_class(property_class); + i_it->source_location.set_function(i_it->function); } } else if(i_it->is_assert()) @@ -1346,9 +1371,11 @@ void instrument_cover_goals( // check whether the current goal already exists if(goals.is_existing_goal(source_location) && !source_location.get_file().empty() && - source_location.get_file()[0]!='<') + source_location.get_file()[0]!='<' && + cover_curr_function) { - std::string comment="block "+b; + std::string comment="function "+id2string(i_it->function)+" block "+b; + const irep_idt function=i_it->function; goto_program.insert_before_swap(i_it); i_it->make_assertion(false_exprt()); i_it->source_location=source_location; @@ -1356,7 +1383,7 @@ void instrument_cover_goals( i_it->source_location.set( ID_coverage_criterion, coverage_criterion); i_it->source_location.set_property_class(property_class); - + i_it->source_location.set_function(function); i_it++; } } @@ -1367,7 +1394,8 @@ void instrument_cover_goals( if(i_it->is_assert()) i_it->make_skip(); - if(i_it==goto_program.instructions.begin()) + if(i_it==goto_program.instructions.begin() && + cover_curr_function) { // we want branch coverage to imply 'entry point of function' // coverage @@ -1382,6 +1410,7 @@ void instrument_cover_goals( t->source_location.set_comment(comment); t->source_location.set(ID_coverage_criterion, coverage_criterion); t->source_location.set_property_class(property_class); + t->source_location.set_function(i_it->function); } if(i_it->is_goto() && !i_it->guard.is_true()) @@ -1394,6 +1423,7 @@ void instrument_cover_goals( exprt guard=i_it->guard; source_locationt source_location=i_it->source_location; + source_location.set_function(i_it->function); goto_program.insert_before_swap(i_it); i_it->make_assertion(not_exprt(guard)); @@ -1419,6 +1449,7 @@ void instrument_cover_goals( i_it->make_skip(); // Conditions are all atomic predicates in the programs. + if(cover_curr_function) { const std::set conditions=collect_conditions(i_it); @@ -1429,12 +1460,14 @@ void instrument_cover_goals( const std::string c_string=from_expr(ns, "", c); const std::string comment_t="condition `"+c_string+"' true"; + const irep_idt function=i_it->function; goto_program.insert_before_swap(i_it); i_it->make_assertion(c); i_it->source_location=source_location; i_it->source_location.set_comment(comment_t); i_it->source_location.set(ID_coverage_criterion, coverage_criterion); i_it->source_location.set_property_class(property_class); + i_it->source_location.set_function(function); const std::string comment_f="condition `"+c_string+"' false"; goto_program.insert_before_swap(i_it); @@ -1443,6 +1476,7 @@ void instrument_cover_goals( i_it->source_location.set_comment(comment_f); i_it->source_location.set(ID_coverage_criterion, coverage_criterion); i_it->source_location.set_property_class(property_class); + i_it->source_location.set_function(function); } for(std::size_t i=0; imake_skip(); // Decisions are maximal Boolean combinations of conditions. + if(cover_curr_function) { const std::set decisions=collect_decisions(i_it); @@ -1465,12 +1500,14 @@ void instrument_cover_goals( const std::string d_string=from_expr(ns, "", d); const std::string comment_t="decision `"+d_string+"' true"; + const irep_idt function=i_it->function; goto_program.insert_before_swap(i_it); i_it->make_assertion(d); i_it->source_location=source_location; i_it->source_location.set_comment(comment_t); i_it->source_location.set(ID_coverage_criterion, coverage_criterion); i_it->source_location.set_property_class(property_class); + i_it->source_location.set_function(function); const std::string comment_f="decision `"+d_string+"' false"; goto_program.insert_before_swap(i_it); @@ -1479,6 +1516,7 @@ void instrument_cover_goals( i_it->source_location.set_comment(comment_f); i_it->source_location.set(ID_coverage_criterion, coverage_criterion); i_it->source_location.set_property_class(property_class); + i_it->source_location.set_function(function); } for(std::size_t i=0; i conditions=collect_conditions(i_it); const std::set decisions=collect_decisions(i_it); @@ -1521,6 +1560,7 @@ void instrument_cover_goals( std::string p_string=from_expr(ns, "", p); std::string comment_t=description+" `"+p_string+"' true"; + const irep_idt function=i_it->function; goto_program.insert_before_swap(i_it); // i_it->make_assertion(p); i_it->make_assertion(not_exprt(p)); @@ -1528,6 +1568,7 @@ void instrument_cover_goals( i_it->source_location.set_comment(comment_t); i_it->source_location.set(ID_coverage_criterion, coverage_criterion); i_it->source_location.set_property_class(property_class); + i_it->source_location.set_function(function); std::string comment_f=description+" `"+p_string+"' false"; goto_program.insert_before_swap(i_it); @@ -1537,6 +1578,7 @@ void instrument_cover_goals( i_it->source_location.set_comment(comment_f); i_it->source_location.set(ID_coverage_criterion, coverage_criterion); i_it->source_location.set_property_class(property_class); + i_it->source_location.set_function(function); } std::set controlling; @@ -1554,6 +1596,7 @@ void instrument_cover_goals( std::string description= "MC/DC independence condition `"+p_string+"'"; + const irep_idt function=i_it->function; goto_program.insert_before_swap(i_it); i_it->make_assertion(not_exprt(p)); // i_it->make_assertion(p); @@ -1561,6 +1604,7 @@ void instrument_cover_goals( i_it->source_location.set_comment(description); i_it->source_location.set(ID_coverage_criterion, coverage_criterion); i_it->source_location.set_property_class(property_class); + i_it->source_location.set_function(function); } for(std::size_t i=0; isecond.body, criterion, - goals); + goals, + function_only, + ignore_trivial); } } @@ -1627,61 +1675,16 @@ Function: instrument_cover_goals void instrument_cover_goals( const symbol_tablet &symbol_table, goto_functionst &goto_functions, - coverage_criteriont criterion) -{ - Forall_goto_functions(f_it, goto_functions) - { - if(f_it->first==ID__start || - f_it->first=="__CPROVER_initialize") - continue; - - // empty set of existing goals - coverage_goalst goals; - instrument_cover_goals(symbol_table, f_it->second.body, - criterion, goals); - } -} - -/*******************************************************************\ - -Function: consider_goals - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -bool consider_goals( - const goto_programt &goto_program, - coverage_goalst &goals) + coverage_criteriont criterion, + bool function_only) { - // check whether we should eliminate trivial goals - if(!goals.get_no_trivial_tests()) - return true; - - bool result; - unsigned long count_assignments=0, count_goto=0, count_decl=0; - - forall_goto_program_instructions(i_it, goto_program) - { - if(i_it->is_goto()) - ++count_goto; - else if(i_it->is_assign()) - ++count_assignments; - else if(i_it->is_decl()) - ++count_decl; - } - - // check whether this is a constructor/destructor or a get/set (pattern) - if(!count_goto && !count_assignments && !count_decl) - result=false; - else - result = !((count_decl==0) && (count_goto<=1) && - (count_assignments>0 && count_assignments<5)); - - return result; + //empty set of existing goals + coverage_goalst goals; + instrument_cover_goals( + symbol_table, + goto_functions, + criterion, + goals, + function_only, + false); } - diff --git a/src/goto-instrument/cover.h b/src/goto-instrument/cover.h index 07ced79178c..afe74e04a77 100644 --- a/src/goto-instrument/cover.h +++ b/src/goto-instrument/cover.h @@ -16,11 +16,10 @@ Date: May 2016 class coverage_goalst { public: - coverage_goalst(); static coverage_goalst get_coverage_goals(const std::string &coverage, message_handlert &message_handler); - void set_goals(source_locationt goal); - bool is_existing_goal(source_locationt source_location); + void add_goal(source_locationt goal); + bool is_existing_goal(source_locationt source_location) const; void set_no_trivial_tests(const bool trivial); const bool get_no_trivial_tests(); @@ -38,21 +37,32 @@ bool consider_goals( const goto_programt &goto_program, coverage_goalst &goals); +void instrument_cover_goals( + const symbol_tablet &symbol_table, + goto_functionst &goto_functions, + coverage_criteriont, + bool function_only=false); + void instrument_cover_goals( const symbol_tablet &symbol_table, goto_programt &goto_program, coverage_criteriont, - coverage_goalst &goals); + bool function_only=false); void instrument_cover_goals( const symbol_tablet &symbol_table, goto_functionst &goto_functions, coverage_criteriont, - coverage_goalst &goals); + const coverage_goalst &goals, + bool function_only=false, + bool ignore_trivial=false); void instrument_cover_goals( const symbol_tablet &symbol_table, - goto_functionst &goto_functions, - coverage_criteriont); + goto_programt &goto_program, + coverage_criteriont, + const coverage_goalst &goals, + bool function_only=false, + bool ignore_trivial=false); #endif // CPROVER_GOTO_INSTRUMENT_COVER_H From da849ee28d965f28e5f87b88ae499d79aa032374 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Mon, 13 Mar 2017 15:37:51 +0000 Subject: [PATCH 155/699] Adding conversion for functions of the Java Character library This processing of java method calls is meant to replace simple methods of the Character Java by expressions on characters. About 60% of the library is supported, but for some of this methods are limited to ASCII characters. This is meant to be run in conjunction with the string refinement so it is called if the string-refine option is activated. Rename conversion_input to conversion_inputt Corrected linting issues --- src/java_bytecode/Makefile | 4 +- .../character_refine_preprocess.cpp | 2513 +++++++++++++++++ .../character_refine_preprocess.h | 152 + 3 files changed, 2668 insertions(+), 1 deletion(-) create mode 100644 src/java_bytecode/character_refine_preprocess.cpp create mode 100644 src/java_bytecode/character_refine_preprocess.h diff --git a/src/java_bytecode/Makefile b/src/java_bytecode/Makefile index 20958a3ede3..8a672b4e899 100644 --- a/src/java_bytecode/Makefile +++ b/src/java_bytecode/Makefile @@ -6,7 +6,9 @@ SRC = java_bytecode_language.cpp java_bytecode_parse_tree.cpp \ java_root_class.cpp java_bytecode_parser.cpp bytecode_info.cpp \ java_class_loader.cpp jar_file.cpp java_object_factory.cpp \ java_bytecode_convert_method.cpp java_local_variable_table.cpp \ - java_pointer_casts.cpp java_utils.cpp + java_pointer_casts.cpp java_utils.cpp \ + character_refine_preprocess.cpp \ + # Empty last line INCLUDES= -I .. diff --git a/src/java_bytecode/character_refine_preprocess.cpp b/src/java_bytecode/character_refine_preprocess.cpp new file mode 100644 index 00000000000..ea7ff1becf7 --- /dev/null +++ b/src/java_bytecode/character_refine_preprocess.cpp @@ -0,0 +1,2513 @@ +/*******************************************************************\ + +Module: Preprocess a goto-programs so that calls to the java Character + library are replaced by simple expressions. + +Author: Romain Brenguier + +Date: March 2017 + +\*******************************************************************/ + +#include +#include +#include "character_refine_preprocess.h" + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_char_function + + Inputs: + expr_function - A reference to a function on expressions + target - A position in a goto program + + Purpose: converts based on a function on expressions + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_char_function( + exprt (*expr_function)(const exprt &chr, const typet &type), + conversion_inputt &target) +{ + const code_function_callt &function_call=target; + assert(function_call.arguments().size()==1); + const exprt &arg=function_call.arguments()[0]; + const exprt &result=function_call.lhs(); + const typet &type=result.type(); + return code_assignt(result, expr_function(arg, type)); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::in_interval_expr + + Inputs: + arg - Expression we want to bound + lower_bound - Integer lower bound + upper_bound - Integer upper bound + + Outputs: A Boolean expression + + Purpose: The returned expression is true when the first argument is in the + interval defined by the lower and upper bounds (included) + +\*******************************************************************/ + +exprt character_refine_preprocesst::in_interval_expr( + const exprt &chr, + const mp_integer &lower_bound, + const mp_integer &upper_bound) +{ + return and_exprt( + binary_relation_exprt(chr, ID_ge, from_integer(lower_bound, chr.type())), + binary_relation_exprt(chr, ID_le, from_integer(upper_bound, chr.type()))); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::in_list_expr + + Inputs: + chr - An expression of type character + list - A list of integer representing unicode characters + + Outputs: A Boolean expression + + Purpose: The returned expression is true when the given character + is equal to one of the element in the list + +\*******************************************************************/ + +exprt character_refine_preprocesst::in_list_expr( + const exprt &chr, const std::list &list) +{ + exprt::operandst ops; + for(const auto &i : list) + ops.push_back(equal_exprt(chr, from_integer(i, chr.type()))); + return disjunction(ops); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_char_count + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: A integer expression of the given type + + Purpose: Determines the number of char values needed to represent + the specified character (Unicode code point). + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_char_count( + const exprt &chr, const typet &type) +{ + exprt u010000=from_integer(0x010000, type); + binary_relation_exprt small(chr, ID_lt, u010000); + return if_exprt(small, from_integer(1, type), from_integer(2, type)); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_char_count + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.charCount:(I)I + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_char_count( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_char_count, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_char_value + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: An expression of the given type + + Purpose: Casts the given expression to the given type + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_char_value( + const exprt &chr, const typet &type) +{ + return typecast_exprt(chr, type); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_char_value + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.charValue:()C + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_char_value( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_char_value, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_compare + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.compare:(CC)I + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_compare(conversion_inputt &target) +{ + const code_function_callt &function_call=target; + assert(function_call.arguments().size()==2); + const exprt &char1=function_call.arguments()[0]; + const exprt &char2=function_call.arguments()[1]; + const exprt &result=function_call.lhs(); + const typet &type=result.type(); + binary_relation_exprt smaller(char1, ID_lt, char2); + binary_relation_exprt greater(char1, ID_gt, char2); + if_exprt expr( + smaller, + from_integer(-1, type), + if_exprt(greater, from_integer(1, type), from_integer(0, type))); + + return code_assignt(result, expr); +} + + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_digit_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.digit:(CI)I + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_digit_char( + conversion_inputt &target) +{ + const code_function_callt &function_call=target; + assert(function_call.arguments().size()==2); + const exprt &arg=function_call.arguments()[0]; + const exprt &radix=function_call.arguments()[1]; + const exprt &result=function_call.lhs(); + const typet &type=result.type(); + + // TODO: If the radix is not in the range MIN_RADIX <= radix <= MAX_RADIX or + // if the value of ch is not a valid digit in the specified radix, + // -1 is returned. + + // Case 1: The method isDigit is true of the character and the Unicode + // decimal digit value of the character (or its single-character + // decomposition) is less than the specified radix. + exprt invalid=from_integer(-1, arg.type()); + exprt c0=from_integer('0', arg.type()); + exprt latin_digit=in_interval_expr(arg, '0', '9'); + minus_exprt value1(arg, c0); + // TODO: this is only valid for latin digits + if_exprt case1( + binary_relation_exprt(value1, ID_lt, radix), value1, invalid); + + // Case 2: The character is one of the uppercase Latin letters 'A' + // through 'Z' and its code is less than radix + 'A' - 10, + // then ch - 'A' + 10 is returned. + exprt cA=from_integer('A', arg.type()); + exprt i10=from_integer(10, arg.type()); + exprt upper_case=in_interval_expr(arg, 'A', 'Z'); + plus_exprt value2(minus_exprt(arg, cA), i10); + if_exprt case2( + binary_relation_exprt(value2, ID_lt, radix), value2, invalid); + + // The character is one of the lowercase Latin letters 'a' through 'z' and + // its code is less than radix + 'a' - 10, then ch - 'a' + 10 is returned. + exprt ca=from_integer('a', arg.type()); + exprt lower_case=in_interval_expr(arg, 'a', 'z'); + plus_exprt value3(minus_exprt(arg, ca), i10); + if_exprt case3( + binary_relation_exprt(value3, ID_lt, radix), value3, invalid); + + + // The character is one of the fullwidth uppercase Latin letters A ('\uFF21') + // through Z ('\uFF3A') and its code is less than radix + '\uFF21' - 10. + // In this case, ch - '\uFF21' + 10 is returned. + exprt uFF21=from_integer(0xFF21, arg.type()); + exprt fullwidth_upper_case=in_interval_expr(arg, 0xFF21, 0xFF3A); + plus_exprt value4(minus_exprt(arg, uFF21), i10); + if_exprt case4( + binary_relation_exprt(value4, ID_lt, radix), value4, invalid); + + // The character is one of the fullwidth lowercase Latin letters a ('\uFF41') + // through z ('\uFF5A') and its code is less than radix + '\uFF41' - 10. + // In this case, ch - '\uFF41' + 10 is returned. + exprt uFF41=from_integer(0xFF41, arg.type()); + plus_exprt value5(minus_exprt(arg, uFF41), i10); + if_exprt case5( + binary_relation_exprt(value5, ID_lt, radix), value5, invalid); + + if_exprt fullwidth_cases(fullwidth_upper_case, case4, case5); + if_exprt expr( + latin_digit, + case1, + if_exprt(upper_case, case2, if_exprt(lower_case, case3, fullwidth_cases))); + typecast_exprt tc_expr(expr, type); + + return code_assignt(result, tc_expr); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_char_is_digit_int + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.digit:(II)I + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_digit_int(conversion_inputt &target) +{ + return convert_digit_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_for_digit + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.forDigit:(II)I + + TODO: For now the radix argument is ignored + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_for_digit(conversion_inputt &target) +{ + const code_function_callt &function_call=target; + assert(function_call.arguments().size()==2); + const exprt &digit=function_call.arguments()[0]; + const exprt &result=function_call.lhs(); + const typet &type=result.type(); + + exprt d10=from_integer(10, type); + binary_relation_exprt small(digit, ID_le, d10); + plus_exprt value1(digit, from_integer('0', type)); + minus_exprt value2(plus_exprt(digit, from_integer('a', digit.type())), d10); + return code_assignt(result, if_exprt(small, value1, value2)); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_get_directionality_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.getDirectionality:(C)I + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_get_directionality_char( + conversion_inputt &target) +{ + // TODO: This is unimplemented for now as it requires analyzing + // the UnicodeData file to find characters directionality. + return target; +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_char_is_digit_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.getDirectionality:(I)I + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_get_directionality_int( + conversion_inputt &target) +{ + return convert_get_directionality_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_get_numeric_value_char + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.getNumericValue:(C)I + + TODO: For now this is only for ASCII characters + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_get_numeric_value_char( + conversion_inputt &target) +{ + return convert_digit_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_get_numeric_value_int + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.getNumericValue:(C)I + + TODO: For now this is only for ASCII characters + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_get_numeric_value_int( + conversion_inputt &target) +{ + return convert_digit_int(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_get_type_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.getType:(C)I + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_get_type_char( + conversion_inputt &target) +{ + // TODO: This is unimplemented for now as it requires analyzing + // the UnicodeData file to categorize characters. + return target; +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_get_type_int + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.getType:(I)I + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_get_type_int( + conversion_inputt &target) +{ + return convert_get_type_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_hash_code + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.hashCode:()I + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_hash_code(conversion_inputt &target) +{ + return convert_char_value(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_high_surrogate + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: An expression of the given type + + Purpose: Returns the leading surrogate (a high surrogate code unit) + of the surrogate pair representing the specified + supplementary character (Unicode code point) in the UTF-16 + encoding. + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_high_surrogate( + const exprt &chr, const typet &type) +{ + exprt u10000=from_integer(0x010000, type); + exprt uD800=from_integer(0xD800, type); + exprt u400=from_integer(0x0400, type); + + plus_exprt high_surrogate(uD800, div_exprt(minus_exprt(chr, u10000), u400)); + return high_surrogate; +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_high_surrogate + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.highSurrogate:(C)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_high_surrogate( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_high_surrogate, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_ascii_lower_case + + Inputs: + chr - An expression of type character + type - A type for the output + + Outputs: A Boolean expression + + Purpose: Determines if the specified character is an ASCII lowercase + character. + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_ascii_lower_case( + const exprt &chr, const typet &type) +{ + return in_interval_expr(chr, 'a', 'z'); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_ascii_upper_case + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: A Boolean expression + + Purpose: Determines if the specified character is an ASCII uppercase + character. + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_ascii_upper_case( + const exprt &chr, const typet &type) +{ + return in_interval_expr(chr, 'A', 'Z'); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_letter + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: An expression of the given type + + Purpose: Determines if the specified character is a letter. + + TODO: for now this is only for ASCII characters, the + following unicode categories are not yet considered: + TITLECASE_LETTER MODIFIER_LETTER OTHER_LETTER LETTER_NUMBER + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_letter( + const exprt &chr, const typet &type) +{ + return or_exprt( + expr_of_is_ascii_upper_case(chr, type), + expr_of_is_ascii_lower_case(chr, type)); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_alphabetic + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: An expression of the given type + + Purpose: Determines if the specified character (Unicode code point) + is alphabetic. + + TODO: for now this is only for ASCII characters, the + following unicode categorise are not yet considered: + TITLECASE_LETTER MODIFIER_LETTER OTHER_LETTER LETTER_NUMBER + and contributory property Other_Alphabetic as defined by the + Unicode Standard. + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_alphabetic( + const exprt &chr, const typet &type) +{ + return expr_of_is_letter(chr, type); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_alphabetic + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isAlphabetic:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_alphabetic( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_alphabetic, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_bmp_code_point + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: A Boolean expression + + Purpose: Determines whether the specified character (Unicode code + point) is in the Basic Multilingual Plane (BMP). Such code + points can be represented using a single char. + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_bmp_code_point( + const exprt &chr, const typet &type) +{ + binary_relation_exprt is_bmp(chr, ID_le, from_integer(0xFFFF, chr.type())); + return is_bmp; +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_bmp_code_point + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isBmpCodePoint:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_bmp_code_point( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_bmp_code_point, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_for_is_defined + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: An expression of the given type + + Purpose: Determines if a character is defined in Unicode. + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_defined( + const exprt &chr, const typet &type) +{ + // The following intervals are undefined in unicode, according to + // the Unicode Character Database: http://www.unicode.org/Public/UCD/latest/ + exprt::operandst intervals; + intervals.push_back(in_interval_expr(chr, 0x0750, 0x077F)); + intervals.push_back(in_interval_expr(chr, 0x07C0, 0x08FF)); + intervals.push_back(in_interval_expr(chr, 0x1380, 0x139F)); + intervals.push_back(in_interval_expr(chr, 0x18B0, 0x18FF)); + intervals.push_back(in_interval_expr(chr, 0x1980, 0x19DF)); + intervals.push_back(in_interval_expr(chr, 0x1A00, 0x1CFF)); + intervals.push_back(in_interval_expr(chr, 0x1D80, 0x1DFF)); + intervals.push_back(in_interval_expr(chr, 0x2C00, 0x2E7F)); + intervals.push_back(in_interval_expr(chr, 0x2FE0, 0x2FEF)); + intervals.push_back(in_interval_expr(chr, 0x31C0, 0x31EF)); + intervals.push_back(in_interval_expr(chr, 0x9FB0, 0x9FFF)); + intervals.push_back(in_interval_expr(chr, 0xA4D0, 0xABFF)); + intervals.push_back(in_interval_expr(chr, 0xD7B0, 0xD7FF)); + intervals.push_back(in_interval_expr(chr, 0xFE10, 0xFE1F)); + intervals.push_back(in_interval_expr(chr, 0x10140, 0x102FF)); + intervals.push_back(in_interval_expr(chr, 0x104B0, 0x107FF)); + intervals.push_back(in_interval_expr(chr, 0x10840, 0x1CFFF)); + intervals.push_back(in_interval_expr(chr, 0x1D200, 0x1D2FF)); + intervals.push_back(in_interval_expr(chr, 0x1D360, 0x1D3FF)); + intervals.push_back( + binary_relation_exprt(chr, ID_ge, from_integer(0x1D800, chr.type()))); + + return not_exprt(disjunction(intervals)); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_defined_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isDefined:(C)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_defined_char( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_defined, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_char_is_digit_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isDefined:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_defined_int( + conversion_inputt &target) +{ + return convert_is_defined_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_digit + + Inputs: + chr - An expression of type character + type - A type for the output + + Outputs: An expression of the given type + + Purpose: Determines if the specified character is a digit. + A character is a digit if its general category type, + provided by Character.getType(ch), is DECIMAL_DIGIT_NUMBER. + + TODO: for now we only support these ranges of digits: + '\u0030' through '\u0039', ISO-LATIN-1 digits ('0' through '9') + '\u0660' through '\u0669', Arabic-Indic digits + '\u06F0' through '\u06F9', Extended Arabic-Indic digits + '\u0966' through '\u096F', Devanagari digits + '\uFF10' through '\uFF19', Fullwidth digits + Many other character ranges contain digits as well. + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_digit( + const exprt &chr, const typet &type) +{ + exprt latin_digit=in_interval_expr(chr, '0', '9'); + exprt arabic_indic_digit=in_interval_expr(chr, 0x660, 0x669); + exprt extended_digit=in_interval_expr(chr, 0x6F0, 0x6F9); + exprt devanagari_digit=in_interval_expr(chr, 0x966, 0x96F); + exprt fullwidth_digit=in_interval_expr(chr, 0xFF10, 0xFF19); + or_exprt digit( + or_exprt(latin_digit, or_exprt(arabic_indic_digit, extended_digit)), + or_exprt(devanagari_digit, fullwidth_digit)); + return digit; +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_digit_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isDigit:(C)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_digit_char( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_digit, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_digit_int + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.digit:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_digit_int( + conversion_inputt &target) +{ + return convert_is_digit_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_high_surrogate + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: A Boolean expression + + Purpose: Determines if the given char value is a Unicode + high-surrogate code unit (also known as leading-surrogate + code unit). + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_high_surrogate( + const exprt &chr, const typet &type) +{ + return in_interval_expr(chr, 0xD800, 0xDBFF); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_high_surrogate + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isHighSurrogate:(C)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_high_surrogate( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_high_surrogate, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_identifier_ignorable + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: A Boolean expression + + Purpose: Determines if the character is one of ignorable in a Java + identifier, that is, it is in one of these ranges: + '\u0000' through '\u0008' + '\u000E' through '\u001B' + '\u007F' through '\u009F' + + TODO: For now, we ignore the FORMAT general category value + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_identifier_ignorable( + const exprt &chr, const typet &type) +{ + or_exprt ignorable( + in_interval_expr(chr, 0x0000, 0x0008), + or_exprt( + in_interval_expr(chr, 0x000E, 0x001B), + in_interval_expr(chr, 0x007F, 0x009F))); + return ignorable; +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_identifier_ignorable_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method + Character.isIdentifierIgnorable:(C)Z + + TODO: For now, we ignore the FORMAT general category value + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_identifier_ignorable_char( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_identifier_ignorable, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_identifier_ignorable_int + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method + Character.isIdentifierIgnorable:(I)Z + + TODO: For now, we ignore the FORMAT general category value + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_identifier_ignorable_int( + conversion_inputt &target) +{ + return convert_is_identifier_ignorable_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_ideographic + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isIdeographic:(C)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_ideographic( + conversion_inputt &target) +{ + const code_function_callt &function_call=target; + assert(function_call.arguments().size()==1); + const exprt &arg=function_call.arguments()[0]; + const exprt &result=function_call.lhs(); + exprt is_ideograph=in_interval_expr(arg, 0x4E00, 0x9FFF); + return code_assignt(result, is_ideograph); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_ISO_control_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isISOControl:(C)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_ISO_control_char( + conversion_inputt &target) +{ + const code_function_callt &function_call=target; + assert(function_call.arguments().size()==1); + const exprt &arg=function_call.arguments()[0]; + const exprt &result=function_call.lhs(); + or_exprt iso( + in_interval_expr(arg, 0x00, 0x1F), in_interval_expr(arg, 0x7F, 0x9F)); + return code_assignt(result, iso); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_ISO_control_int + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isISOControl:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_ISO_control_int( + conversion_inputt &target) +{ + return convert_is_ISO_control_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_java_identifier_part_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isJavaIdentifierPart:(C)Z + + TODO: For now we do not allow currency symbol, connecting punctuation, + combining mark, non-spacing mark + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_java_identifier_part_char( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_unicode_identifier_part, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_java_identifier_part_int + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method isJavaIdentifierPart:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_java_identifier_part_int( + conversion_inputt &target) +{ + return convert_is_unicode_identifier_part_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_java_identifier_start_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method isJavaIdentifierStart:(C)Z + + TODO: For now we only allow letters and letter numbers. + The java specification for this function is not precise on the + other characters. + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_java_identifier_start_char( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_unicode_identifier_part, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_char_is_digit_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method isJavaIdentifierStart:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_java_identifier_start_int( + conversion_inputt &target) +{ + return convert_is_java_identifier_start_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_java_letter + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isJavaLetter:(C)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_java_letter( + conversion_inputt &target) +{ + return convert_is_java_identifier_start_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_java_letter_or_digit + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method isJavaLetterOrDigit:(C)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_java_letter_or_digit( + conversion_inputt &target) +{ + return convert_is_java_identifier_part_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_letter_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isLetter:(C)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_letter_char( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_letter, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_letter_int + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isLetter:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_letter_int( + conversion_inputt &target) +{ + return convert_is_letter_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_letter_or_digit + + Inputs: + chr - An expression of type character + type - A type for the output + + Outputs: An expression of the given type + + Purpose: Determines if the specified character is a letter or digit. + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_letter_or_digit( + const exprt &chr, const typet &type) +{ + return or_exprt(expr_of_is_letter(chr, type), expr_of_is_digit(chr, type)); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_letter_or_digit_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isLetterOrDigit:(C)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_letter_or_digit_char( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_digit, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_letter_or_digit_int + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isLetterOrDigit:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_letter_or_digit_int( + conversion_inputt &target) +{ + return convert_is_letter_or_digit_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_lower_case_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isLowerCase:(C)Z + + TODO: For now we only consider ASCII characters + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_lower_case_char( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_ascii_lower_case, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_lower_case_int() + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isLowerCase:(I)Z + + TODO: For now we only consider ASCII characters + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_lower_case_int( + conversion_inputt &target) +{ + return convert_is_lower_case_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_low_surrogate + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isLowSurrogate:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_low_surrogate( + conversion_inputt &target) +{ + const code_function_callt &function_call=target; + assert(function_call.arguments().size()==1); + const exprt &arg=function_call.arguments()[0]; + const exprt &result=function_call.lhs(); + exprt is_low_surrogate=in_interval_expr(arg, 0xDC00, 0xDFFF); + return code_assignt(result, is_low_surrogate); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_mirrored + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: An expression of the given type + + Purpose: Determines whether the character is mirrored according to + the Unicode specification. + + TODO: For now only ASCII characters are considered + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_mirrored( + const exprt &chr, const typet &type) +{ + return in_list_expr(chr, {0x28, 0x29, 0x3C, 0x3E, 0x5B, 0x5D, 0x7B, 0x7D}); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_mirrored_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isMirrored:(C)Z + + TODO: For now only ASCII characters are considered + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_mirrored_char( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_mirrored, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_mirrored_int + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isMirrored:(I)Z + + TODO: For now only ASCII characters are considered + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_mirrored_int( + conversion_inputt &target) +{ + return convert_is_mirrored_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_space + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isSpace:(C)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_space(conversion_inputt &target) +{ + return convert_is_whitespace_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_space_char + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: A Boolean expression + + Purpose: Determines if the specified character is white space + according to Unicode (SPACE_SEPARATOR, LINE_SEPARATOR, or + PARAGRAPH_SEPARATOR) + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_space_char( + const exprt &chr, const typet &type) +{ + std::list space_characters= + {0x20, 0x00A0, 0x1680, 0x202F, 0x205F, 0x3000, 0x2028, 0x2029}; + exprt condition0=in_list_expr(chr, space_characters); + exprt condition1=in_interval_expr(chr, 0x2000, 0x200A); + return or_exprt(condition0, condition1); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_space_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isSpaceChar:(C)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_space_char( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_space_char, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_space_char_int() + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isSpaceChar:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_space_char_int( + conversion_inputt &target) +{ + return convert_is_space_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_supplementary_code_point + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: A Boolean expression + + Purpose: Determines whether the specified character (Unicode code + point) is in the supplementary character range. + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_supplementary_code_point( + const exprt &chr, const typet &type) +{ + return binary_relation_exprt(chr, ID_gt, from_integer(0xFFFF, chr.type())); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_supplementary_code_point + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method + Character.isSupplementaryCodePoint:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_supplementary_code_point( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_supplementary_code_point, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_surrogate + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: A Boolean expression + + Purpose: Determines if the given char value is a Unicode surrogate + code unit. + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_surrogate( + const exprt &chr, const typet &type) +{ + return in_interval_expr(chr, 0xD800, 0xDFFF); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_surrogate + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isSurrogate:(C)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_surrogate( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_surrogate, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_surrogate_pair + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isSurrogatePair:(CC)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_surrogate_pair( + conversion_inputt &target) +{ + const code_function_callt &function_call=target; + assert(function_call.arguments().size()==2); + const exprt &arg0=function_call.arguments()[0]; + const exprt &arg1=function_call.arguments()[1]; + const exprt &result=function_call.lhs(); + exprt is_low_surrogate=in_interval_expr(arg1, 0xDC00, 0xDFFF); + exprt is_high_surrogate=in_interval_expr(arg0, 0xD800, 0xDBFF); + return code_assignt(result, and_exprt(is_high_surrogate, is_low_surrogate)); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_title_case + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: A Boolean expression + + Purpose: Determines if the specified character is a titlecase character. + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_title_case( + const exprt &chr, const typet &type) +{ + std::listtitle_case_chars= + {0x01C5, 0x01C8, 0x01CB, 0x01F2, 0x1FBC, 0x1FCC, 0x1FFC}; + exprt::operandst conditions; + conditions.push_back(in_list_expr(chr, title_case_chars)); + conditions.push_back(in_interval_expr(chr, 0x1F88, 0x1F8F)); + conditions.push_back(in_interval_expr(chr, 0x1F98, 0x1F9F)); + conditions.push_back(in_interval_expr(chr, 0x1FA8, 0x1FAF)); + return disjunction(conditions); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_title_case_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isTitleCase:(C)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_title_case_char( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_title_case, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_title_case_int + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isTitleCase:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_title_case_int( + conversion_inputt &target) +{ + return convert_is_title_case_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_letter_number + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: A Boolean expression + + Purpose: Determines if the specified character is in the LETTER_NUMBER + category of Unicode + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_letter_number( + const exprt &chr, const typet &type) +{ + // The following set of characters is the general category "Nl" in the + // Unicode specification. + exprt cond0=in_interval_expr(chr, 0x16EE, 0x16F0); + exprt cond1=in_interval_expr(chr, 0x2160, 0x2188); + exprt cond2=in_interval_expr(chr, 0x3021, 0x3029); + exprt cond3=in_interval_expr(chr, 0x3038, 0x303A); + exprt cond4=in_interval_expr(chr, 0xA6E6, 0xA6EF); + exprt cond5=in_interval_expr(chr, 0x10140, 0x10174); + exprt cond6=in_interval_expr(chr, 0x103D1, 0x103D5); + exprt cond7=in_interval_expr(chr, 0x12400, 0x1246E); + exprt cond8=in_list_expr(chr, {0x3007, 0x10341, 0x1034A}); + return or_exprt( + or_exprt(or_exprt(cond0, cond1), or_exprt(cond2, cond3)), + or_exprt(or_exprt(cond4, cond5), or_exprt(cond6, or_exprt(cond7, cond8)))); +} + + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_unicode_identifier_part + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: A Boolean expression + + Purpose: Determines if the character may be part of a Unicode identifier. + + TODO: For now we do not allow connecting punctuation, combining mark, + non-spacing mark + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_unicode_identifier_part( + const exprt &chr, const typet &type) +{ + exprt::operandst conditions; + conditions.push_back(expr_of_is_unicode_identifier_start(chr, type)); + conditions.push_back(expr_of_is_digit(chr, type)); + conditions.push_back(expr_of_is_identifier_ignorable(chr, type)); + return disjunction(conditions); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_unicode_identifier_part_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method + Character.isUnicodeIdentifierPart:(C)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_unicode_identifier_part_char( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_unicode_identifier_part, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_unicode_identifier_part_int + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method + Character.isUnicodeIdentifierPart:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_unicode_identifier_part_int( + conversion_inputt &target) +{ + return convert_is_unicode_identifier_part_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_unicode_identifier_start + + Inputs: + chr - An expression of type character + type - A type for the output + + Outputs: A Boolean expression + + Purpose: Determines if the specified character is permissible as the + first character in a Unicode identifier. + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_unicode_identifier_start( + const exprt &chr, const typet &type) +{ + return or_exprt( + expr_of_is_letter(chr, type), expr_of_is_letter_number(chr, type)); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_unicode_identifier_start_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method + Character.isUnicodeIdentifierStart:(C)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_unicode_identifier_start_char( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_unicode_identifier_start, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_unicode_identifier_start_int + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method + Character.isUnicodeIdentifierStart:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_unicode_identifier_start_int( + conversion_inputt &target) +{ + return convert_is_unicode_identifier_start_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_upper_case_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isUpperCase:(C)Z + + TODO: For now we only consider ASCII characters + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_upper_case_char( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_ascii_upper_case, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_upper_case_int + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isUpperCase:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_upper_case_int( + conversion_inputt &target) +{ + return convert_is_upper_case_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_valid_code_point + + Inputs: + chr - An expression of type character + type - A type for the output + + Outputs: A Boolean expression + + Purpose: Determines whether the specified code point is a valid + Unicode code point value. + That is, in the range of integers from 0 to 0x10FFFF + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_valid_code_point( + const exprt &chr, const typet &type) +{ + return binary_relation_exprt(chr, ID_le, from_integer(0x10FFFF, chr.type())); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_valid_code_point + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isValidCodePoint:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_valid_code_point( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_valid_code_point, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_is_whitespace + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: A Boolean expression + + Purpose: Determines if the specified character is white space according + to Java. It is the case when it one of the following: + * a Unicode space character (SPACE_SEPARATOR, LINE_SEPARATOR, or + PARAGRAPH_SEPARATOR) but is not also a non-breaking space + ('\u00A0', '\u2007', '\u202F'). + * it is one of these: U+0009 U+000A U+000B U+000C U+000D + U+001C U+001D U+001E U+001F + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_is_whitespace( + const exprt &chr, const typet &type) +{ + exprt::operandst conditions; + std::list space_characters= + {0x20, 0x1680, 0x205F, 0x3000, 0x2028, 0x2029}; + conditions.push_back(in_list_expr(chr, space_characters)); + conditions.push_back(in_interval_expr(chr, 0x2000, 0x2006)); + conditions.push_back(in_interval_expr(chr, 0x2008, 0x200A)); + conditions.push_back(in_interval_expr(chr, 0x09, 0x0D)); + conditions.push_back(in_interval_expr(chr, 0x1C, 0x1F)); + return disjunction(conditions); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_whitespace_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isWhitespace:(C)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_whitespace_char( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_is_whitespace, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_is_whitespace_int + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.isWhitespace:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_is_whitespace_int( + conversion_inputt &target) +{ + return convert_is_whitespace_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_low_surrogate + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: A integer expression of the given type + + Purpose: Returns the trailing surrogate (a low surrogate code unit) + of the surrogate pair representing the specified + supplementary character (Unicode code point) in the UTF-16 + encoding. + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_low_surrogate( + const exprt &chr, const typet &type) +{ + exprt uDC00=from_integer(0xDC00, type); + exprt u0400=from_integer(0x0400, type); + return plus_exprt(uDC00, mod_exprt(chr, u0400)); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_low_surrogate + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.lowSurrogate:(I)Z + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_low_surrogate( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_low_surrogate, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_reverse_bytes + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: A character expression of the given type + + Purpose: Returns the value obtained by reversing the order of the + bytes in the specified char value. + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_reverse_bytes( + const exprt &chr, const typet &type) +{ + shl_exprt first_byte(chr, from_integer(8, type)); + lshr_exprt second_byte(chr, from_integer(8, type)); + return plus_exprt(first_byte, second_byte); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_reverse_bytes + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.reverseBytes:(C)C + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_reverse_bytes( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_reverse_bytes, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_to_chars + + Inputs: + expr - An expression of type character + type - A type for the output + + Outputs: A character array expression of the given type + + Purpose: Converts the specified character (Unicode code point) to + its UTF-16 representation stored in a char array. + If the specified code point is a BMP (Basic Multilingual + Plane or Plane 0) value, the resulting char array has the + same value as codePoint. + If the specified code point is a supplementary code point, + the resulting char array has the corresponding surrogate pair. + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_to_chars( + const exprt &chr, const typet &type) +{ + array_typet array_type=to_array_type(type); + const typet &char_type=array_type.subtype(); + array_exprt case1(array_type); + array_exprt case2(array_type); + exprt low_surrogate=expr_of_low_surrogate(chr, char_type); + case1.copy_to_operands(low_surrogate); + case2.move_to_operands(low_surrogate); + exprt high_surrogate=expr_of_high_surrogate(chr, char_type); + case2.move_to_operands(high_surrogate); + return if_exprt(expr_of_is_bmp_code_point(chr, type), case1, case2); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_to_chars + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.toChars:(I)[C + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_to_chars(conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_to_chars, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_to_code_point + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.toCodePoint:(CC)I + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_to_code_point( + conversion_inputt &target) +{ + const code_function_callt &function_call=target; + assert(function_call.arguments().size()==2); + const exprt &arg0=function_call.arguments()[0]; + const exprt &arg1=function_call.arguments()[1]; + const exprt &result=function_call.lhs(); + const typet &type=result.type(); + + // These operations implement the decoding of a unicode symbol encoded + // in UTF16 for the supplementary planes (above U+10000). + // The low ten bits of the first character give the bits 10 to 19 of + // code point and the low ten bits of the second give the bits 0 to 9, + // then 0x10000 is added to the result. For more explenations see: + // https://en.wikipedia.org/wiki/UTF-16 + + exprt u010000=from_integer(0x010000, type); + exprt mask10bit=from_integer(0x03FF, type); + shl_exprt m1(bitand_exprt(arg0, mask10bit), from_integer(10, type)); + bitand_exprt m2(arg1, mask10bit); + bitor_exprt pair_value(u010000, bitor_exprt(m1, m2)); + return code_assignt(result, pair_value); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_to_lower_case + + Inputs: + chr - An expression of type character + type - A type for the output + + Outputs: An expression of the given type + + Purpose: Converts the character argument to lowercase. + + TODO: For now we only consider ASCII characters but ultimately + we should use case mapping information from the + UnicodeData file + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_to_lower_case( + const exprt &chr, const typet &type) +{ + minus_exprt transformed( + plus_exprt(chr, from_integer('a', type)), from_integer('A', type)); + + if_exprt res(expr_of_is_ascii_upper_case(chr, type), transformed, chr); + return res; +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_to_lower_case_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.toLowerCase:(C)C + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_to_lower_case_char( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_to_lower_case, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_to_lower_case_int() + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.toLowerCase:(I)I + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_to_lower_case_int( + conversion_inputt &target) +{ + return convert_to_lower_case_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_to_title_case + + Inputs: + chr - An expression of type character + type - A type for the output + + Outputs: An expression of the given type + + Purpose: Converts the character argument to titlecase. + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_to_title_case( + const exprt &chr, const typet &type) +{ + std::list increment_list={0x01C4, 0x01C7, 0x01CA, 0x01F1}; + std::list decrement_list={0x01C6, 0x01C9, 0x01CC, 0x01F3}; + exprt plus_8_interval1=in_interval_expr(chr, 0x1F80, 0x1F87); + exprt plus_8_interval2=in_interval_expr(chr, 0x1F90, 0x1F97); + exprt plus_8_interval3=in_interval_expr(chr, 0x1FA0, 0x1FA7); + std::list plus_9_list={0x1FB3, 0x1FC3, 0x1FF3}; + minus_exprt minus_1(chr, from_integer(1, type)); + plus_exprt plus_1(chr, from_integer(1, type)); + plus_exprt plus_8(chr, from_integer(8, type)); + plus_exprt plus_9(chr, from_integer(9, type)); + or_exprt plus_8_set( + plus_8_interval1, or_exprt(plus_8_interval2, plus_8_interval3)); + + if_exprt res( + in_list_expr(chr, increment_list), + plus_1, + if_exprt( + in_list_expr(chr, decrement_list), + minus_1, + if_exprt( + plus_8_set, + plus_8, + if_exprt( + in_list_expr(chr, plus_9_list), + plus_9, + chr)))); + + return res; +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_to_title_case_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.toTitleCase:(C)C + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_to_title_case_char( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_to_title_case, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_to_title_case_int + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.toTitleCase:(I)I + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_to_title_case_int( + conversion_inputt &target) +{ + return convert_to_title_case_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::expr_of_to_upper_case + + Inputs: + chr - An expression of type character + type - A type for the output + + Outputs: An expression of the given type + + Purpose: Converts the character argument to uppercase. + + TODO: For now we only consider ASCII characters but ultimately + we should use case mapping information from the + UnicodeData file + +\*******************************************************************/ + +exprt character_refine_preprocesst::expr_of_to_upper_case( + const exprt &chr, const typet &type) +{ + minus_exprt transformed( + plus_exprt(chr, from_integer('A', type)), from_integer('a', type)); + + if_exprt res(expr_of_is_ascii_lower_case(chr, type), transformed, chr); + return res; +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_to_upper_case_char + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.toUpperCase:(C)C + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_to_upper_case_char( + conversion_inputt &target) +{ + return convert_char_function( + &character_refine_preprocesst::expr_of_to_upper_case, target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::convert_to_upper_case_int + + Inputs: + target - a position in a goto program + + Purpose: Converts function call to an assignment of an expression + corresponding to the java method Character.toUpperCase:(I)I + +\*******************************************************************/ + +codet character_refine_preprocesst::convert_to_upper_case_int( + conversion_inputt &target) +{ + return convert_to_upper_case_char(target); +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::replace_character_call + + Inputs: + code - the code of a function call + + Outputs: code where character function call get replaced by + an simple instruction + + Purpose: replace function calls to functions of the Character by + an affectation if possible, returns the same code otherwise. + For this method to have an effect initialize_conversion_table + must have been called before. + +\*******************************************************************/ + +codet character_refine_preprocesst::replace_character_call( + const code_function_callt &code) const +{ + if(code.function().id()==ID_symbol) + { + const irep_idt &function_id= + to_symbol_expr(code.function()).get_identifier(); + auto it=conversion_table.find(function_id); + if(it!=conversion_table.end()) + return (it->second)(code); + } + + return code; +} + +/*******************************************************************\ + +Function: character_refine_preprocesst::initialize_conversion_table + + Purpose: fill maps with correspondance from java method names to + conversion functions + +\*******************************************************************/ + +void character_refine_preprocesst::initialize_conversion_table() +{ + // All methods are listed here in alphabetic order + // The ones that are not supported by this module (though they may be + // supported by the string solver) have no entry in the conversion + // table and are marked in this way: + // Not supported "java::java.lang.Character.()" + + conversion_table["java::java.lang.Character.charCount:(I)I"]= + &character_refine_preprocesst::convert_char_count; + conversion_table["java::java.lang.Character.charValue:()C"]= + &character_refine_preprocesst::convert_char_value; + + // Not supported "java::java.lang.Character.codePointAt:([CI)I + // Not supported "java::java.lang.Character.codePointAt:([CII)I" + // Not supported "java::java.lang.Character.codePointAt:" + // "(Ljava.lang.CharSequence;I)I" + // Not supported "java::java.lang.Character.codePointBefore:([CI)I" + // Not supported "java::java.lang.Character.codePointBefore:([CII)I" + // Not supported "java::java.lang.Character.codePointBefore:" + // "(Ljava.lang.CharSequence;I)I" + // Not supported "java::java.lang.Character.codePointCount:([CII)I" + // Not supported "java::java.lang.Character.codePointCount:" + // "(Ljava.lang.CharSequence;I)I" + // Not supported "java::java.lang.Character.compareTo:" + // "(Ljava.lang.Character;)I" + + conversion_table["java::java.lang.Character.compare:(CC)I"]= + &character_refine_preprocesst::convert_compare; + conversion_table["java::java.lang.Character.digit:(CI)I"]= + &character_refine_preprocesst::convert_digit_char; + conversion_table["java::java.lang.Character.digit:(II)I"]= + &character_refine_preprocesst::convert_digit_int; + + // Not supported "java::java.lang.Character.equals:(Ljava.lang.Object;)Z" + + conversion_table["java::java.lang.Character.forDigit:(II)C"]= + &character_refine_preprocesst::convert_for_digit; + conversion_table["java::java.lang.Character.getDirectionality:(C)B"]= + &character_refine_preprocesst::convert_get_directionality_char; + conversion_table["java::java.lang.Character.getDirectionality:(I)B"]= + &character_refine_preprocesst::convert_get_directionality_int; + + // Not supported "java::java.lang.Character.getName:(I)Ljava.lang.String;" + + conversion_table["java::java.lang.Character.getNumericValue:(C)I"]= + &character_refine_preprocesst::convert_get_numeric_value_char; + conversion_table["java::java.lang.Character.getNumericValue:(I)I"]= + &character_refine_preprocesst::convert_get_numeric_value_int; + conversion_table["java::java.lang.Character.getType:(C)I"]= + &character_refine_preprocesst::convert_get_type_char; + conversion_table["java::java.lang.Character.getType:(I)Z"]= + &character_refine_preprocesst::convert_get_type_int; + conversion_table["java::java.lang.Character.hashCode:()I"]= + &character_refine_preprocesst::convert_hash_code; + conversion_table["java::java.lang.Character.highSurrogate:(C)Z"]= + &character_refine_preprocesst::convert_high_surrogate; + conversion_table["java::java.lang.Character.isAlphabetic:(I)Z"]= + &character_refine_preprocesst::convert_is_alphabetic; + conversion_table["java::java.lang.Character.isBmpCodePoint:(I)Z"]= + &character_refine_preprocesst::convert_is_bmp_code_point; + conversion_table["java::java.lang.Character.isDefined:(C)Z"]= + &character_refine_preprocesst::convert_is_defined_char; + conversion_table["java::java.lang.Character.isDefined:(I)Z"]= + &character_refine_preprocesst::convert_is_defined_int; + conversion_table["java::java.lang.Character.isDigit:(C)Z"]= + &character_refine_preprocesst::convert_is_digit_char; + conversion_table["java::java.lang.Character.isDigit:(I)Z"]= + &character_refine_preprocesst::convert_is_digit_int; + conversion_table["java::java.lang.Character.isHighSurrogate:(C)Z"]= + &character_refine_preprocesst::convert_is_high_surrogate; + conversion_table["java::java.lang.Character.isIdentifierIgnorable:(C)Z"]= + &character_refine_preprocesst::convert_is_identifier_ignorable_char; + conversion_table["java::java.lang.Character.isIdentifierIgnorable:(I)Z"]= + &character_refine_preprocesst::convert_is_identifier_ignorable_int; + conversion_table["java::java.lang.Character.isIdeographic:(C)Z"]= + &character_refine_preprocesst::convert_is_ideographic; + conversion_table["java::java.lang.Character.isISOControl:(C)Z"]= + &character_refine_preprocesst::convert_is_ISO_control_char; + conversion_table["java::java.lang.Character.isISOControl:(I)Z"]= + &character_refine_preprocesst::convert_is_ISO_control_int; + conversion_table["java::java.lang.Character.isJavaIdentifierPart:(C)Z"]= + &character_refine_preprocesst::convert_is_java_identifier_part_char; + conversion_table["java::java.lang.Character.isJavaIdentifierPart:(I)Z"]= + &character_refine_preprocesst::convert_is_java_identifier_part_int; + conversion_table["java::java.lang.Character.isJavaIdentifierStart:(C)Z"]= + &character_refine_preprocesst::convert_is_java_identifier_start_char; + conversion_table["java::java.lang.Character.isJavaIdentifierStart:(I)Z"]= + &character_refine_preprocesst::convert_is_java_identifier_start_int; + conversion_table["java::java.lang.Character.isJavaLetter:(C)Z"]= + &character_refine_preprocesst::convert_is_java_letter; + conversion_table["java::java.lang.Character.isJavaLetterOrDigit:(C)Z"]= + &character_refine_preprocesst::convert_is_java_letter_or_digit; + conversion_table["java::java.lang.Character.isLetter:(C)Z"]= + &character_refine_preprocesst::convert_is_letter_char; + conversion_table["java::java.lang.Character.isLetter:(I)Z"]= + &character_refine_preprocesst::convert_is_letter_int; + conversion_table["java::java.lang.Character.isLetterOrDigit:(C)Z"]= + &character_refine_preprocesst::convert_is_letter_or_digit_char; + conversion_table["java::java.lang.Character.isLetterOrDigit:(I)Z"]= + &character_refine_preprocesst::convert_is_letter_or_digit_int; + conversion_table["java::java.lang.Character.isLowerCase:(C)Z"]= + &character_refine_preprocesst::convert_is_lower_case_char; + conversion_table["java::java.lang.Character.isLowerCase:(I)Z"]= + &character_refine_preprocesst::convert_is_lower_case_int; + conversion_table["java::java.lang.Character.isLowSurrogate:(I)Z"]= + &character_refine_preprocesst::convert_is_low_surrogate; + conversion_table["java::java.lang.Character.isMirrored:(C)Z"]= + &character_refine_preprocesst::convert_is_mirrored_char; + conversion_table["java::java.lang.Character.isMirrored:(I)Z"]= + &character_refine_preprocesst::convert_is_mirrored_int; + conversion_table["java::java.lang.Character.isSpace:(C)Z"]= + &character_refine_preprocesst::convert_is_space; + conversion_table["java::java.lang.Character.isSpaceChar:(C)Z"]= + &character_refine_preprocesst::convert_is_space_char; + conversion_table["java::java.lang.Character.isSpaceChar:(I)Z"]= + &character_refine_preprocesst::convert_is_space_char_int; + conversion_table["java::java.lang.Character.isSupplementaryCodePoint:(I)Z"]= + &character_refine_preprocesst::convert_is_supplementary_code_point; + conversion_table["java::java.lang.Character.isSurrogate:(C)Z"]= + &character_refine_preprocesst::convert_is_surrogate; + conversion_table["java::java.lang.Character.isSurrogatePair:(CC)Z"]= + &character_refine_preprocesst::convert_is_surrogate_pair; + conversion_table["java::java.lang.Character.isTitleCase:(C)Z"]= + &character_refine_preprocesst::convert_is_title_case_char; + conversion_table["java::java.lang.Character.isTitleCase:(I)Z"]= + &character_refine_preprocesst::convert_is_title_case_int; + conversion_table["java::java.lang.Character.isUnicodeIdentifierPart:(C)Z"]= + &character_refine_preprocesst::convert_is_unicode_identifier_part_char; + conversion_table["java::java.lang.Character.isUnicodeIdentifierPart:(I)Z"]= + &character_refine_preprocesst::convert_is_unicode_identifier_part_int; + conversion_table["java::java.lang.Character.isUnicodeIdentifierStart:(C)Z"]= + &character_refine_preprocesst::convert_is_unicode_identifier_start_char; + conversion_table["java::java.lang.Character.isUnicodeIdentifierStart:(I)Z"]= + &character_refine_preprocesst::convert_is_unicode_identifier_start_int; + conversion_table["java::java.lang.Character.isUpperCase:(C)Z"]= + &character_refine_preprocesst::convert_is_upper_case_char; + conversion_table["java::java.lang.Character.isUpperCase:(I)Z"]= + &character_refine_preprocesst::convert_is_upper_case_int; + conversion_table["java::java.lang.Character.isValidCodePoint:(I)Z"]= + &character_refine_preprocesst::convert_is_valid_code_point; + conversion_table["java::java.lang.Character.isWhitespace:(C)Z"]= + &character_refine_preprocesst::convert_is_whitespace_char; + conversion_table["java::java.lang.Character.isWhitespace:(I)Z"]= + &character_refine_preprocesst::convert_is_whitespace_int; + conversion_table["java::java.lang.Character.lowSurrogate:(I)Z"]= + &character_refine_preprocesst::convert_is_low_surrogate; + + // Not supported "java::java.lang.Character.offsetByCodePoints:([CIIII)I" + // Not supported "java::java.lang.Character.offsetByCodePoints:" + // "(Ljava.lang.CharacterSequence;II)I" + + conversion_table["java::java.lang.Character.reverseBytes:(C)C"]= + &character_refine_preprocesst::convert_reverse_bytes; + conversion_table["java::java.lang.Character.toChars:(I)[C"]= + &character_refine_preprocesst::convert_to_chars; + + // Not supported "java::java.lang.Character.toChars:(I[CI])I" + + conversion_table["java::java.lang.Character.toCodePoint:(CC)I"]= + &character_refine_preprocesst::convert_to_code_point; + conversion_table["java::java.lang.Character.toLowerCase:(C)C"]= + &character_refine_preprocesst::convert_to_lower_case_char; + conversion_table["java::java.lang.Character.toLowerCase:(I)I"]= + &character_refine_preprocesst::convert_to_lower_case_int; + + // Not supported "java::java.lang.Character.toString:()Ljava.lang.String;" + // Not supported "java::java.lang.Character.toString:(C)Ljava.lang.String;" + + conversion_table["java::java.lang.Character.toTitleCase:(C)C"]= + &character_refine_preprocesst::convert_to_title_case_char; + conversion_table["java::java.lang.Character.toTitleCase:(I)I"]= + &character_refine_preprocesst::convert_to_title_case_int; + conversion_table["java::java.lang.Character.toUpperCase:(C)C"]= + &character_refine_preprocesst::convert_to_upper_case_char; + conversion_table["java::java.lang.Character.toUpperCase:(I)I"]= + &character_refine_preprocesst::convert_to_upper_case_int; + + // Not supported "java::java.lang.Character.valueOf:(C)Ljava.lang.Character;" +} diff --git a/src/java_bytecode/character_refine_preprocess.h b/src/java_bytecode/character_refine_preprocess.h new file mode 100644 index 00000000000..45f76a5d5b6 --- /dev/null +++ b/src/java_bytecode/character_refine_preprocess.h @@ -0,0 +1,152 @@ +/*******************************************************************\ + +Module: Preprocess a goto-programs so that calls to the java Character + library are replaced by simple expressions. + For now support is limited to character in the ASCII range, + some methods may have incorrect specifications outside of this range. + +Author: Romain Brenguier + +Date: March 2017 + +\*******************************************************************/ + +#ifndef CPROVER_JAVA_BYTECODE_CHARACTER_REFINE_PREPROCESS_H +#define CPROVER_JAVA_BYTECODE_CHARACTER_REFINE_PREPROCESS_H + +#include +#include + +class character_refine_preprocesst:public messaget +{ +public: + void initialize_conversion_table(); + codet replace_character_call(const code_function_callt &call) const; + +private: + typedef const code_function_callt &conversion_inputt; + typedef codet (*conversion_functiont)(conversion_inputt &target); + // A table tells us what method to call for each java method signature + std::unordered_map + conversion_table; + + // Conversion functions + static exprt expr_of_char_count(const exprt &chr, const typet &type); + static codet convert_char_count(conversion_inputt &target); + static exprt expr_of_char_value(const exprt &chr, const typet &type); + static codet convert_char_value(conversion_inputt &target); + static codet convert_compare(conversion_inputt &target); + static codet convert_digit_char(conversion_inputt &target); + static codet convert_digit_int(conversion_inputt &target); + static codet convert_for_digit(conversion_inputt &target); + static codet convert_get_directionality_char(conversion_inputt &target); + static codet convert_get_directionality_int(conversion_inputt &target); + static codet convert_get_numeric_value_char(conversion_inputt &target); + static codet convert_get_numeric_value_int(conversion_inputt &target); + static codet convert_get_type_char(conversion_inputt &target); + static codet convert_get_type_int(conversion_inputt &target); + static codet convert_hash_code(conversion_inputt &target); + static exprt expr_of_high_surrogate(const exprt &chr, const typet &type); + static codet convert_high_surrogate(conversion_inputt &target); + static exprt expr_of_is_alphabetic(const exprt &chr, const typet &type); + static codet convert_is_alphabetic(conversion_inputt &target); + static exprt expr_of_is_bmp_code_point(const exprt &chr, const typet &type); + static codet convert_is_bmp_code_point(conversion_inputt &target); + static exprt expr_of_is_defined(const exprt &chr, const typet &type); + static codet convert_is_defined_char(conversion_inputt &target); + static codet convert_is_defined_int(conversion_inputt &target); + static exprt expr_of_is_digit(const exprt &chr, const typet &type); + static codet convert_is_digit_char(conversion_inputt &target); + static codet convert_is_digit_int(conversion_inputt &target); + static exprt expr_of_is_high_surrogate(const exprt &chr, const typet &type); + static codet convert_is_high_surrogate(conversion_inputt &target); + static exprt expr_of_is_identifier_ignorable( + const exprt &chr, const typet &type); + static codet convert_is_identifier_ignorable_char(conversion_inputt &target); + static codet convert_is_identifier_ignorable_int(conversion_inputt &target); + static codet convert_is_ideographic(conversion_inputt &target); + static codet convert_is_ISO_control_char(conversion_inputt &target); + static codet convert_is_ISO_control_int(conversion_inputt &target); + static codet convert_is_java_identifier_part_char(conversion_inputt &target); + static codet convert_is_java_identifier_part_int(conversion_inputt &target); + static codet convert_is_java_identifier_start_char(conversion_inputt &target); + static codet convert_is_java_identifier_start_int(conversion_inputt &target); + static codet convert_is_java_letter(conversion_inputt &target); + static codet convert_is_java_letter_or_digit(conversion_inputt &target); + static exprt expr_of_is_letter(const exprt &chr, const typet &type); + static codet convert_is_letter_char(conversion_inputt &target); + static codet convert_is_letter_int(conversion_inputt &target); + static exprt expr_of_is_letter_or_digit(const exprt &chr, const typet &type); + static codet convert_is_letter_or_digit_char(conversion_inputt &target); + static codet convert_is_letter_or_digit_int(conversion_inputt &target); + static exprt expr_of_is_ascii_lower_case(const exprt &chr, const typet &type); + static codet convert_is_lower_case_char(conversion_inputt &target); + static codet convert_is_lower_case_int(conversion_inputt &target); + static codet convert_is_low_surrogate(conversion_inputt &target); + static exprt expr_of_is_mirrored(const exprt &chr, const typet &type); + static codet convert_is_mirrored_char(conversion_inputt &target); + static codet convert_is_mirrored_int(conversion_inputt &target); + static codet convert_is_space(conversion_inputt &target); + static exprt expr_of_is_space_char(const exprt &chr, const typet &type); + static codet convert_is_space_char(conversion_inputt &target); + static codet convert_is_space_char_int(conversion_inputt &target); + static exprt expr_of_is_supplementary_code_point( + const exprt &chr, const typet &type); + static codet convert_is_supplementary_code_point(conversion_inputt &target); + static exprt expr_of_is_surrogate(const exprt &chr, const typet &type); + static codet convert_is_surrogate(conversion_inputt &target); + static codet convert_is_surrogate_pair(conversion_inputt &target); + static exprt expr_of_is_title_case(const exprt &chr, const typet &type); + static codet convert_is_title_case_char(conversion_inputt &target); + static codet convert_is_title_case_int(conversion_inputt &target); + static exprt expr_of_is_letter_number(const exprt &chr, const typet &type); + static exprt expr_of_is_unicode_identifier_part( + const exprt &chr, const typet &type); + static codet convert_is_unicode_identifier_part_char( + conversion_inputt &target); + static codet convert_is_unicode_identifier_part_int( + conversion_inputt &target); + static exprt expr_of_is_unicode_identifier_start( + const exprt &chr, const typet &type); + static codet convert_is_unicode_identifier_start_char( + conversion_inputt &target); + static codet convert_is_unicode_identifier_start_int( + conversion_inputt &target); + static exprt expr_of_is_ascii_upper_case(const exprt &chr, const typet &type); + static codet convert_is_upper_case_char(conversion_inputt &target); + static codet convert_is_upper_case_int(conversion_inputt &target); + static exprt expr_of_is_valid_code_point(const exprt &chr, const typet &type); + static codet convert_is_valid_code_point(conversion_inputt &target); + static exprt expr_of_is_whitespace(const exprt &chr, const typet &type); + static codet convert_is_whitespace_char(conversion_inputt &target); + static codet convert_is_whitespace_int(conversion_inputt &target); + static exprt expr_of_low_surrogate(const exprt &chr, const typet &type); + static codet convert_low_surrogate(conversion_inputt &target); + static exprt expr_of_reverse_bytes(const exprt &chr, const typet &type); + static codet convert_reverse_bytes(conversion_inputt &target); + static exprt expr_of_to_chars(const exprt &chr, const typet &type); + static codet convert_to_chars(conversion_inputt &target); + static codet convert_to_code_point(conversion_inputt &target); + static exprt expr_of_to_lower_case(const exprt &chr, const typet &type); + static codet convert_to_lower_case_char(conversion_inputt &target); + static codet convert_to_lower_case_int(conversion_inputt &target); + static exprt expr_of_to_title_case(const exprt &chr, const typet &type); + static codet convert_to_title_case_char(conversion_inputt &target); + static codet convert_to_title_case_int(conversion_inputt &target); + static exprt expr_of_to_upper_case(const exprt &chr, const typet &type); + static codet convert_to_upper_case_char(conversion_inputt &target); + static codet convert_to_upper_case_int(conversion_inputt &target); + + // Helper functions + static codet convert_char_function( + exprt (*expr_function)(const exprt &chr, const typet &type), + conversion_inputt &target); + static exprt in_interval_expr( + const exprt &chr, + const mp_integer &lower_bound, + const mp_integer &upper_bound); + static exprt in_list_expr( + const exprt &chr, const std::list &list); +}; + +#endif // CPROVER_JAVA_BYTECODE_CHARACTER_REFINE_PREPROCESS_H From dead0224b107ebb947cb68e22e28d922822b867c Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Mon, 27 Mar 2017 13:17:06 +0100 Subject: [PATCH 156/699] Corrected type problem for the function Character.forDigit:(II)C --- src/java_bytecode/character_refine_preprocess.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/java_bytecode/character_refine_preprocess.cpp b/src/java_bytecode/character_refine_preprocess.cpp index ea7ff1becf7..79c134670f9 100644 --- a/src/java_bytecode/character_refine_preprocess.cpp +++ b/src/java_bytecode/character_refine_preprocess.cpp @@ -306,7 +306,7 @@ Function: character_refine_preprocesst::convert_for_digit target - a position in a goto program Purpose: Converts function call to an assignment of an expression - corresponding to the java method Character.forDigit:(II)I + corresponding to the java method Character.forDigit:(II)C TODO: For now the radix argument is ignored @@ -319,11 +319,12 @@ codet character_refine_preprocesst::convert_for_digit(conversion_inputt &target) const exprt &digit=function_call.arguments()[0]; const exprt &result=function_call.lhs(); const typet &type=result.type(); + typecast_exprt casted_digit(digit, type); exprt d10=from_integer(10, type); - binary_relation_exprt small(digit, ID_le, d10); - plus_exprt value1(digit, from_integer('0', type)); - minus_exprt value2(plus_exprt(digit, from_integer('a', digit.type())), d10); + binary_relation_exprt small(casted_digit, ID_le, d10); + plus_exprt value1(casted_digit, from_integer('0', type)); + plus_exprt value2(minus_exprt(casted_digit, d10), from_integer('a', type)); return code_assignt(result, if_exprt(small, value1, value2)); } From 91d07b1e114872fcbfc5fa2d5c78dc162717f5ca Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Thu, 16 Mar 2017 14:54:57 +0000 Subject: [PATCH 157/699] Bug corrections in string refinement Case of array-of in substitute array access making substitute_array_access do in-place substitution Setting the type for unknown values in substitute_array_access Unknown values could cause type problems if we do not force the type for them. Setting ui for temporary solver Remove the mode option from string solver This option is no longer requiered because the implementation is now language independent. Adapt add_axioms_for_insert for 5 arguments #110 Fixed linting issue in string_constraint_generator_concat.cpp Comment on the maximal length for string Using max_string_length as the limit for refinement Using unsigned type for max string length Using const ref in substitute_array_with_expr Correcting type of max_string_length and length comparison functions space before & sign instead of after Correcting initial_loop_bound type Putting each cbmc option on a separate line for easy merging Use size_t for string sizes Add comment in concretize_string --- src/cbmc/cbmc_parse_options.h | 5 +- .../refinement/string_constraint_generator.h | 17 +- .../string_constraint_generator_concat.cpp | 3 +- .../string_constraint_generator_insert.cpp | 25 ++- .../string_constraint_generator_main.cpp | 4 +- src/solvers/refinement/string_refinement.cpp | 169 ++++++++++++++---- src/solvers/refinement/string_refinement.h | 11 +- src/util/string_expr.h | 6 +- 8 files changed, 173 insertions(+), 67 deletions(-) diff --git a/src/cbmc/cbmc_parse_options.h b/src/cbmc/cbmc_parse_options.h index 4bdc07a6278..2c54dfc7353 100644 --- a/src/cbmc/cbmc_parse_options.h +++ b/src/cbmc/cbmc_parse_options.h @@ -38,7 +38,10 @@ class optionst; "(no-sat-preprocessor)" \ "(no-pretty-names)(beautify)" \ "(dimacs)(refine)(max-node-refinement):(refine-arrays)(refine-arithmetic)"\ - "(refine-strings)(string-non-empty)(string-printable)(string-max-length):" \ + "(refine-strings)" \ + "(string-non-empty)" \ + "(string-printable)" \ + "(string-max-length):" \ "(aig)(16)(32)(64)(LP64)(ILP64)(LLP64)(ILP32)(LP32)" \ "(little-endian)(big-endian)" \ "(show-goto-functions)(show-loops)" \ diff --git a/src/solvers/refinement/string_constraint_generator.h b/src/solvers/refinement/string_constraint_generator.h index d8f3f17326e..163adc5aab7 100644 --- a/src/solvers/refinement/string_constraint_generator.h +++ b/src/solvers/refinement/string_constraint_generator.h @@ -13,6 +13,7 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com #ifndef CPROVER_SOLVERS_REFINEMENT_STRING_CONSTRAINT_GENERATOR_H #define CPROVER_SOLVERS_REFINEMENT_STRING_CONSTRAINT_GENERATOR_H +#include #include #include #include @@ -22,30 +23,20 @@ class string_constraint_generatort { public: // This module keeps a list of axioms. It has methods which generate - // string constraints for different string funcitons and add them + // string constraints for different string functions and add them // to the axiom list. string_constraint_generatort(): - mode(ID_unknown), - max_string_length(-1), + max_string_length(std::numeric_limits::max()), force_printable_characters(false) { } // Constraints on the maximal length of strings - int max_string_length; + size_t max_string_length; // Should we add constraints on the characters bool force_printable_characters; - void set_mode(irep_idt _mode) - { - // only C and java modes supported - assert((_mode==ID_java) || (_mode==ID_C)); - mode=_mode; - } - - irep_idt &get_mode() { return mode; } - // Axioms are of three kinds: universally quantified string constraint, // not contains string constraints and simple formulas. std::list axioms; diff --git a/src/solvers/refinement/string_constraint_generator_concat.cpp b/src/solvers/refinement/string_constraint_generator_concat.cpp index eb841cc5b04..e6f360585bb 100644 --- a/src/solvers/refinement/string_constraint_generator_concat.cpp +++ b/src/solvers/refinement/string_constraint_generator_concat.cpp @@ -35,7 +35,8 @@ string_exprt string_constraint_generatort::add_axioms_for_concat( // a4 : forall i<|s1|. res[i]=s1[i] // a5 : forall i<|s2|. res[i+|s1|]=s2[i] - equal_exprt a1(res.length(), plus_exprt_with_overflow_check(s1.length(), s2.length())); + equal_exprt a1( + res.length(), plus_exprt_with_overflow_check(s1.length(), s2.length())); axioms.push_back(a1); axioms.push_back(s1.axiom_for_is_shorter_than(res)); axioms.push_back(s2.axiom_for_is_shorter_than(res)); diff --git a/src/solvers/refinement/string_constraint_generator_insert.cpp b/src/solvers/refinement/string_constraint_generator_insert.cpp index cd5f4376a93..7a63279699e 100644 --- a/src/solvers/refinement/string_constraint_generator_insert.cpp +++ b/src/solvers/refinement/string_constraint_generator_insert.cpp @@ -40,17 +40,32 @@ Function: string_constraint_generatort::add_axioms_for_insert Outputs: a new string expression - Purpose: add axioms corresponding to the StringBuilder.insert(String) java - function + Purpose: add axioms corresponding to the + StringBuilder.insert(int, CharSequence) + and StringBuilder.insert(int, CharSequence, int, int) + java functions \*******************************************************************/ string_exprt string_constraint_generatort::add_axioms_for_insert( const function_application_exprt &f) { - string_exprt s1=get_string_expr(args(f, 3)[0]); - string_exprt s2=get_string_expr(args(f, 3)[2]); - return add_axioms_for_insert(s1, s2, args(f, 3)[1]); + assert(f.arguments().size()>=3); + string_exprt s1=get_string_expr(f.arguments()[0]); + string_exprt s2=get_string_expr(f.arguments()[2]); + const exprt &offset=f.arguments()[1]; + if(f.arguments().size()==5) + { + const exprt &start=f.arguments()[3]; + const exprt &end=f.arguments()[4]; + string_exprt substring=add_axioms_for_substring(s2, start, end); + return add_axioms_for_insert(s1, substring, offset); + } + else + { + assert(f.arguments().size()==3); + return add_axioms_for_insert(s1, s2, offset); + } } /*******************************************************************\ diff --git a/src/solvers/refinement/string_constraint_generator_main.cpp b/src/solvers/refinement/string_constraint_generator_main.cpp index f081ac26f47..c0a6efef0c1 100644 --- a/src/solvers/refinement/string_constraint_generator_main.cpp +++ b/src/solvers/refinement/string_constraint_generator_main.cpp @@ -224,7 +224,6 @@ Function: string_constraint_generatort::convert_java_string_to_string_exprt string_exprt string_constraint_generatort::convert_java_string_to_string_exprt( const exprt &jls) { - assert(get_mode()==ID_java); assert(jls.id()==ID_struct); exprt length(to_struct_expr(jls).op1()); @@ -269,7 +268,7 @@ void string_constraint_generatort::add_default_axioms( const string_exprt &s) { s.axiom_for_is_longer_than(from_integer(0, s.length().type())); - if(max_string_length>=0) + if(max_string_length!=std::numeric_limits::max()) axioms.push_back(s.axiom_for_is_shorter_than(max_string_length)); if(force_printable_characters) @@ -433,7 +432,6 @@ exprt string_constraint_generatort::add_axioms_for_function_application( // TODO: This part needs some improvement. // Stripping the symbol name is not a very robust process. new_expr.function() = symbol_exprt(str_id.substr(0, pos+4)); - assert(get_mode()==ID_java); new_expr.type() = refined_string_typet(java_int_type(), java_char_type()); auto res_it=function_application_cache.insert(std::make_pair(new_expr, diff --git a/src/solvers/refinement/string_refinement.cpp b/src/solvers/refinement/string_refinement.cpp index 9d2e5627071..0ea7966ef61 100644 --- a/src/solvers/refinement/string_refinement.cpp +++ b/src/solvers/refinement/string_refinement.cpp @@ -49,35 +49,20 @@ string_refinementt::string_refinementt( /*******************************************************************\ -Function: string_refinementt::set_mode - - Purpose: determine which language should be used - -\*******************************************************************/ - -void string_refinementt::set_mode() -{ - debug() << "initializing mode" << eom; - symbolt init=ns.lookup(irep_idt(CPROVER_PREFIX"initialize")); - irep_idt mode=init.mode; - debug() << "mode detected as " << mode << eom; - generator.set_mode(mode); -} - -/*******************************************************************\ - Function: string_refinementt::set_max_string_length Inputs: i - maximum length which is allowed for strings. - negative number means no limit + by default the strings length has no other limit + than the maximal integer according to the type of their + length, for instance 2^31-1 for Java. Purpose: Add constraints on the size of strings used in the program. \*******************************************************************/ -void string_refinementt::set_max_string_length(int i) +void string_refinementt::set_max_string_length(size_t i) { generator.max_string_length=i; } @@ -355,16 +340,18 @@ void string_refinementt::concretize_string(const exprt &expr) if(!to_integer(length, found_length)) { assert(found_length.is_long()); - if(found_length < 0) + if(found_length<0) { + // Lengths should not be negative. + // TODO: Add constraints no the sign of string lengths. debug() << "concretize_results: WARNING found length is negative" << eom; } else { size_t concretize_limit=found_length.to_long(); - concretize_limit=concretize_limit>MAX_CONCRETE_STRING_SIZE? - MAX_CONCRETE_STRING_SIZE:concretize_limit; + concretize_limit=concretize_limit>generator.max_string_length? + generator.max_string_length:concretize_limit; exprt content_expr=str.content(); for(size_t i=0; iMAX_CONCRETE_STRING_SIZE) + if(n>generator.max_string_length) { #if 0 debug() << "(sr::get_array) long string (size=" << n << ")" << eom; @@ -947,6 +928,125 @@ void string_refinementt::fill_model() } +/*******************************************************************\ + +Function: string_refinementt::substitute_array_with_expr() + + Inputs: + expr - A (possibly nested) 'with' expression on an `array_of` + expression + index - An index with which to build the equality condition + + Outputs: An expression containing no 'with' expression + + Purpose: Create a new expression where 'with' expressions on arrays + are replaced by 'if' expressions. + e.g. for an array access arr[x], where: + `arr := array_of(12) with {0:=24} with {2:=42}` + the constructed expression will be: + `index==0 ? 24 : index==2 ? 42 : 12` + +\*******************************************************************/ + +exprt string_refinementt::substitute_array_with_expr( + const exprt &expr, const exprt &index) const +{ + if(expr.id()==ID_with) + { + const with_exprt &with_expr=to_with_expr(expr); + const exprt &then_expr=with_expr.new_value(); + exprt else_expr=substitute_array_with_expr(with_expr.old(), index); + const typet &type=then_expr.type(); + assert(else_expr.type()==type); + return if_exprt( + equal_exprt(index, with_expr.where()), then_expr, else_expr, type); + } + else + { + // Only handle 'with' expressions on 'array_of' expressions. + assert(expr.id()==ID_array_of); + return to_array_of_expr(expr).what(); + } +} + +/*******************************************************************\ + +Function: string_refinementt::substitute_array_access() + + Inputs: + expr - an expression containing array accesses + + Outputs: an expression containing no array access + + Purpose: create an equivalent expression where array accesses and + 'with' expressions are replaced by 'if' expressions. + e.g. for an array access arr[x], where: + `arr := {12, 24, 48}` + the constructed expression will be: + `index==0 ? 12 : index==1 ? 24 : 48` + +\*******************************************************************/ + +void string_refinementt::substitute_array_access(exprt &expr) const +{ + for(auto &op : expr.operands()) + substitute_array_access(op); + + if(expr.id()==ID_index) + { + index_exprt &index_expr=to_index_expr(expr); + + if(index_expr.array().id()==ID_symbol) + { + expr=index_expr; + return; + } + + if(index_expr.array().id()==ID_with) + { + expr=substitute_array_with_expr( + index_expr.array(), index_expr.index()); + return; + } + + if(index_expr.array().id()==ID_array_of) + { + expr=to_array_of_expr(index_expr.array()).op(); + return; + } + + assert(index_expr.array().id()==ID_array); + array_exprt &array_expr=to_array_expr(index_expr.array()); + + assert(!array_expr.operands().empty()); + size_t last_index=array_expr.operands().size()-1; + + const typet &char_type=index_expr.array().type().subtype(); + exprt ite=array_expr.operands().back(); + + if(ite.type()!=char_type) + { + // We have to manualy set the type for unknown values + assert(ite.id()==ID_unknown); + ite.type()=char_type; + } + + auto op_it=++array_expr.operands().rbegin(); + for(size_t i=last_index-1; + op_it!=array_expr.operands().rend(); ++op_it, --i) + { + equal_exprt equals(index_expr.index(), from_integer(i, java_int_type())); + ite=if_exprt(equals, *op_it, ite); + if(ite.type()!=char_type) + { + assert(ite.id()==ID_unknown); + ite.type()=char_type; + } + } + expr=ite; + } +} + /*******************************************************************\ Function: string_refinementt::add_negation_of_constraint_to_solver @@ -991,6 +1091,7 @@ void string_refinementt::add_negation_of_constraint_to_solver( and_exprt negaxiom(premise, not_exprt(axiom.body())); debug() << "(sr::check_axioms) negated axiom: " << from_expr(negaxiom) << eom; + substitute_array_access(negaxiom); solver << negaxiom; } @@ -1031,6 +1132,7 @@ bool string_refinementt::check_axioms() satcheck_no_simplifiert sat_check; supert solver(ns, sat_check); + solver.set_ui(ui); add_negation_of_constraint_to_solver(axiom_in_model, solver); switch(solver()) @@ -1085,6 +1187,7 @@ bool string_refinementt::check_axioms() exprt premise(axiom.premise()); exprt body(axiom.body()); implies_exprt instance(premise, body); + replace_expr(symbol_resolve, instance); replace_expr(axiom.univ_var(), val, instance); debug() << "adding counter example " << from_expr(instance) << eom; add_lemma(instance); diff --git a/src/solvers/refinement/string_refinement.h b/src/solvers/refinement/string_refinement.h index 0163936b069..83f913d5ba9 100644 --- a/src/solvers/refinement/string_refinement.h +++ b/src/solvers/refinement/string_refinement.h @@ -18,11 +18,6 @@ Author: Alberto Griggio, alberto.griggio@gmail.com #include #include -// Defines a limit on the string witnesses we will output. -// Longer strings are still concidered possible by the solver but -// it will not output them. -#define MAX_CONCRETE_STRING_SIZE 500 - #define MAX_NB_REFINEMENT 100 class string_refinementt: public bv_refinementt @@ -41,7 +36,7 @@ class string_refinementt: public bv_refinementt // Should we concretize strings when the solver finished bool do_concretizing; - void set_max_string_length(int i); + void set_max_string_length(size_t i); void enforce_non_empty_string(); void enforce_printable_characters(); @@ -106,8 +101,8 @@ class string_refinementt: public bv_refinementt exprt substitute_function_applications(exprt expr); typet substitute_java_string_types(typet type); exprt substitute_java_strings(exprt expr); - exprt substitute_array_with_expr(exprt &expr, exprt &index) const; - exprt substitute_array_access(exprt &expr) const; + exprt substitute_array_with_expr(const exprt &expr, const exprt &index) const; + void substitute_array_access(exprt &expr) const; void add_symbol_to_symbol_map(const exprt &lhs, const exprt &rhs); bool is_char_array(const typet &type) const; bool add_axioms_for_string_assigns(const exprt &lhs, const exprt &rhs); diff --git a/src/util/string_expr.h b/src/util/string_expr.h index 317e3c1ee6e..ff19a8c8259 100644 --- a/src/util/string_expr.h +++ b/src/util/string_expr.h @@ -74,7 +74,7 @@ class string_exprt: public struct_exprt return binary_relation_exprt(rhs.length(), ID_lt, length()); } - binary_relation_exprt axiom_for_is_strictly_longer_than(int i) const + binary_relation_exprt axiom_for_is_strictly_longer_than(mp_integer i) const { return axiom_for_is_strictly_longer_than(from_integer(i, length().type())); } @@ -91,7 +91,7 @@ class string_exprt: public struct_exprt return binary_relation_exprt(length(), ID_le, rhs); } - binary_relation_exprt axiom_for_is_shorter_than(int i) const + binary_relation_exprt axiom_for_is_shorter_than(mp_integer i) const { return axiom_for_is_shorter_than(from_integer(i, length().type())); } @@ -119,7 +119,7 @@ class string_exprt: public struct_exprt return equal_exprt(length(), rhs); } - equal_exprt axiom_for_has_length(int i) const + equal_exprt axiom_for_has_length(mp_integer i) const { return axiom_for_has_length(from_integer(i, length().type())); } From 161aeee319846a8bb65981f1ddc451823ea01dbf Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 10 Feb 2017 16:23:10 +0000 Subject: [PATCH 158/699] Apply review comments to coverage code Also improve function names, and make boolean functions return the intuitive true=yes, false=no answer instead of error=true. --- src/goto-instrument/cover.cpp | 118 +++++++++++++++++----------------- src/goto-instrument/cover.h | 9 ++- 2 files changed, 62 insertions(+), 65 deletions(-) diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index ed40ce89f0b..6d8573961b9 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -112,59 +112,56 @@ Function: coverage_goalst::get_coverage \*******************************************************************/ -coverage_goalst coverage_goalst::get_coverage_goals(const std::string &coverage, - message_handlert &message_handler) +bool coverage_goalst::get_coverage_goals( + const std::string &coverage_file, + message_handlert &message_handler, + coverage_goalst &goals) { jsont json; - coverage_goalst goals; source_locationt source_location; // check coverage file - if(parse_json(coverage, message_handler, json)) + if(parse_json(coverage_file, message_handler, json)) { messaget message(message_handler); - message.error() << coverage << " file is not a valid json file" + message.error() << coverage_file << " file is not a valid json file" << messaget::eom; - exit(6); + return true; } // make sure that we have an array of elements if(!json.is_array()) { messaget message(message_handler); - message.error() << "expecting an array in the " << coverage + message.error() << "expecting an array in the " << coverage_file << " file, but got " << json << messaget::eom; - exit(6); + return true; } - irep_idt file, function, line; - for(jsont::arrayt::const_iterator - it=json.array.begin(); - it!=json.array.end(); - it++) + for(const auto &goal : json.array) { // get the file of each existing goal - file=(*it)["file"].value; + irep_idt file=goal["file"].value; source_location.set_file(file); // get the function of each existing goal - function=(*it)["function"].value; + irep_idt function=goal["function"].value; source_location.set_function(function); // get the lines array - if((*it)["lines"].is_array()) + if(goal["lines"].is_array()) { - for(const jsont & entry : (*it)["lines"].array) + for(const auto &line_json : goal["lines"].array) { // get the line of each existing goal - line=entry["number"].value; + irep_idt line=line_json["number"].value; source_location.set_line(line); goals.add_goal(source_location); } } } - return goals; + return false; } /*******************************************************************\ @@ -198,19 +195,14 @@ Function: coverage_goalst::is_existing_goal bool coverage_goalst::is_existing_goal(source_locationt source_location) const { - std::vector::const_iterator it = existing_goals.begin(); - while(it!=existing_goals.end()) + for(const auto &existing_loc : existing_goals) { - if(!source_location.get_file().compare(it->get_file()) && - !source_location.get_function().compare(it->get_function()) && - !source_location.get_line().compare(it->get_line())) - break; - ++it; + if(source_location.get_file()==existing_loc.get_file() && + source_location.get_function()==existing_loc.get_function() && + source_location.get_line()==existing_loc.get_line()) + return true; } - if(it == existing_goals.end()) - return true; - else - return false; + return false; } /*******************************************************************\ @@ -1228,46 +1220,51 @@ void instrument_cover_goals( coverage_criteriont criterion, bool function_only) { - coverage_goalst goals; //empty already covered goals - instrument_cover_goals(symbol_table,goto_program, - criterion,goals,function_only,false); + coverage_goalst goals; // empty already covered goals + instrument_cover_goals( + symbol_table, + goto_program, + criterion, + goals, + function_only, + false); } /*******************************************************************\ -Function: consider_goals +Function: program_is_trivial - Inputs: + Inputs: Program `goto_program` - Outputs: + Outputs: Returns true if trivial - Purpose: + Purpose: Call a goto_program trivial unless it has: + * Any declarations + * At least 2 branches + * At least 5 assignments \*******************************************************************/ -bool consider_goals(const goto_programt &goto_program) +bool program_is_trivial(const goto_programt &goto_program) { - bool result; - unsigned long count_assignments=0, count_goto=0, count_decl=0; - + unsigned long count_assignments=0, count_goto=0; forall_goto_program_instructions(i_it, goto_program) { if(i_it->is_goto()) - ++count_goto; - else if (i_it->is_assign()) - ++count_assignments; - else if (i_it->is_decl()) - ++count_decl; + { + if((++count_goto)>=2) + return false; + } + else if(i_it->is_assign()) + { + if((++count_assignments)>=5) + return false; + } + else if(i_it->is_decl()) + return false; } - //check whether this is a constructor/destructor or a get/set (pattern) - if (!count_goto && !count_assignments && !count_decl) - result=false; - else - result = !((count_decl==0) && (count_goto<=1) && - (count_assignments>0 && count_assignments<5)); - - return result; + return true; } /*******************************************************************\ @@ -1290,8 +1287,8 @@ void instrument_cover_goals( bool function_only, bool ignore_trivial) { - //exclude trivial coverage goals of a goto program - if(ignore_trivial && !consider_goals(goto_program)) + // exclude trivial coverage goals of a goto program + if(ignore_trivial && program_is_trivial(goto_program)) return; const namespacet ns(symbol_table); @@ -1369,12 +1366,13 @@ void instrument_cover_goals( basic_blocks.source_location_map[block_nr]; // check whether the current goal already exists - if(goals.is_existing_goal(source_location) && + if(!goals.is_existing_goal(source_location) && !source_location.get_file().empty() && source_location.get_file()[0]!='<' && cover_curr_function) { - std::string comment="function "+id2string(i_it->function)+" block "+b; + std::string comment= + "function "+id2string(i_it->function)+" block "+b; const irep_idt function=i_it->function; goto_program.insert_before_swap(i_it); i_it->make_assertion(false_exprt()); @@ -1647,7 +1645,7 @@ void instrument_cover_goals( Forall_goto_functions(f_it, goto_functions) { if(f_it->first==ID__start || - f_it->first==CPROVER_PREFIX "initialize") + f_it->first==(CPROVER_PREFIX "initialize")) continue; instrument_cover_goals( @@ -1678,7 +1676,7 @@ void instrument_cover_goals( coverage_criteriont criterion, bool function_only) { - //empty set of existing goals + // empty set of existing goals coverage_goalst goals; instrument_cover_goals( symbol_table, diff --git a/src/goto-instrument/cover.h b/src/goto-instrument/cover.h index afe74e04a77..8c2ddcaae5e 100644 --- a/src/goto-instrument/cover.h +++ b/src/goto-instrument/cover.h @@ -16,16 +16,15 @@ Date: May 2016 class coverage_goalst { public: - static coverage_goalst get_coverage_goals(const std::string &coverage, - message_handlert &message_handler); + static bool get_coverage_goals( + const std::string &coverage, + message_handlert &message_handler, + coverage_goalst &goals); void add_goal(source_locationt goal); bool is_existing_goal(source_locationt source_location) const; - void set_no_trivial_tests(const bool trivial); - const bool get_no_trivial_tests(); private: std::vector existing_goals; - bool no_trivial_tests; }; enum class coverage_criteriont From 512d6efa36aeb62adac8f5d8f86942c2a9a55de5 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 7 Apr 2017 14:43:16 +0100 Subject: [PATCH 159/699] Initialise array clsid fields (#770) Not doing this prevented any cast-to-array type from succeeding, which is common e.g. in return from java.lang.Object.clone. --- src/goto-programs/builtin_functions.cpp | 15 ++++++++++++--- src/java_bytecode/java_bytecode_convert_class.cpp | 6 ++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/goto-programs/builtin_functions.cpp b/src/goto-programs/builtin_functions.cpp index b3d6d82f650..359c25dc270 100644 --- a/src/goto-programs/builtin_functions.cpp +++ b/src/goto-programs/builtin_functions.cpp @@ -802,14 +802,21 @@ void goto_convertt::do_java_new_array( t_n->code=code_assignt(lhs, malloc_expr); t_n->source_location=location; - // multi-dimensional? - assert(ns.follow(object_type).id()==ID_struct); const struct_typet &struct_type=to_struct_type(ns.follow(object_type)); assert(struct_type.components().size()==3); - // if it's an array, we need to set the length field + // Init base class: dereference_exprt deref(lhs, object_type); + exprt zero_object= + zero_initializer(object_type, location, ns, get_message_handler()); + set_class_identifier( + to_struct_expr(zero_object), ns, to_symbol_type(object_type)); + goto_programt::targett t_i=dest.add_instruction(ASSIGN); + t_i->code=code_assignt(deref, zero_object); + t_i->source_location=location; + + // if it's an array, we need to set the length field member_exprt length( deref, struct_type.components()[1].get_name(), @@ -842,6 +849,8 @@ void goto_convertt::do_java_new_array( t_d->code=array_set; t_d->source_location=location; + // multi-dimensional? + if(rhs.operands().size()>=2) { // produce diff --git a/src/java_bytecode/java_bytecode_convert_class.cpp b/src/java_bytecode/java_bytecode_convert_class.cpp index 27bc41ba151..4259309fc42 100644 --- a/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/src/java_bytecode/java_bytecode_convert_class.cpp @@ -335,13 +335,19 @@ void java_bytecode_convert_classt::add_array_types() struct_type.components().reserve(3); struct_typet::componentt comp0("@java.lang.Object", symbol_typet("java::java.lang.Object")); + comp0.set_pretty_name("@java.lang.Object"); + comp0.set_base_name("@java.lang.Object"); struct_type.components().push_back(comp0); struct_typet::componentt comp1("length", java_int_type()); + comp1.set_pretty_name("length"); + comp1.set_base_name("length"); struct_type.components().push_back(comp1); struct_typet::componentt comp2("data", pointer_typet(java_type_from_char(l))); + comp2.set_pretty_name("data"); + comp2.set_base_name("data"); struct_type.components().push_back(comp2); symbolt symbol; From ee5d7fc79075cfe192617ab564b6e6b5d91a6a37 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 7 Apr 2017 14:49:30 +0100 Subject: [PATCH 160/699] Run static initializers for enumeration types before all others (#773) Really we should be running them in topographical order (or invoking them at exactly the time the JVM spec says they will be, even better) but this is much less effort and works around the common case that enumeration types are assumed to be initialized by other static init code, which treats them like global constants. --- .../java_bytecode_convert_class.cpp | 3 ++ src/java_bytecode/java_entry_point.cpp | 49 +++++++++++++++++-- 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_class.cpp b/src/java_bytecode/java_bytecode_convert_class.cpp index 4259309fc42..375e916dd3a 100644 --- a/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/src/java_bytecode/java_bytecode_convert_class.cpp @@ -107,9 +107,12 @@ void java_bytecode_convert_classt::convert(const classt &c) class_type.set_tag(c.name); class_type.set(ID_base_name, c.name); if(c.is_enum) + { class_type.set( ID_java_enum_static_unwind, std::to_string(c.enum_elements+1)); + class_type.set(ID_enumeration, true); + } if(!c.extends.empty()) { diff --git a/src/java_bytecode/java_entry_point.cpp b/src/java_bytecode/java_entry_point.cpp index 5234a53200f..e504441bae6 100644 --- a/src/java_bytecode/java_entry_point.cpp +++ b/src/java_bytecode/java_entry_point.cpp @@ -98,6 +98,19 @@ Function: java_static_lifetime_init \*******************************************************************/ +struct static_initializer_callt +{ + symbol_exprt initializer_symbol; + bool is_enum; +}; + +static bool static_initializer_call_enum_lt( + const static_initializer_callt &a, + const static_initializer_callt &b) +{ + return a.is_enum && !b.is_enum; +} + bool java_static_lifetime_init( symbol_tablet &symbol_table, const source_locationt &source_location, @@ -158,6 +171,8 @@ bool java_static_lifetime_init( // we now need to run all the methods + std::vector clinits; + for(symbol_tablet::symbolst::const_iterator it=symbol_table.symbols.begin(); it!=symbol_table.symbols.end(); @@ -167,14 +182,38 @@ bool java_static_lifetime_init( it->second.type.id()==ID_code && it->second.mode==ID_java) { - code_function_callt function_call; - function_call.lhs()=nil_exprt(); - function_call.function()=it->second.symbol_expr(); - function_call.add_source_location()=source_location; - code_block.add(function_call); + const irep_idt symbol_name= + it->second.symbol_expr().get_identifier(); + const std::string &symbol_str=id2string(symbol_name); + const std::string suffix(".:()V"); + assert(has_suffix(symbol_str, suffix)); + const std::string class_symbol_name= + symbol_str.substr(0, symbol_str.size()-suffix.size()); + const symbolt &class_symbol=symbol_table.lookup(class_symbol_name); + clinits.push_back( + { + it->second.symbol_expr(), + class_symbol.type.get_bool(ID_enumeration) + } + ); } } + // Call enumeration initialisers before anything else. + // Really we should be calling them the first time they're referenced, + // as acccording to the JVM spec, but this ought to do the trick for + // most cases with much less effort. + std::sort(clinits.begin(), clinits.end(), static_initializer_call_enum_lt); + + for(const auto &clinit : clinits) + { + code_function_callt function_call; + function_call.lhs()=nil_exprt(); + function_call.function()=clinit.initializer_symbol; + function_call.add_source_location()=source_location; + code_block.add(function_call); + } + return false; } From e610c081e041e8115faccaeb4570142821a6881c Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 7 Apr 2017 14:55:31 +0100 Subject: [PATCH 161/699] Implement Java array.clone (#774) This simply duplicates the contents of an array. Regrettably it uses a loop to do so at this point because if we use ARRAY_COPY the backend dies when it can't conclusively establish that the actual parameters have like type. Some sort of copy-type-from intrinsic would do this, but is more effort than is sensible to make right now. --- regression/cbmc-java/enum1/test.desc | 3 +- .../java_bytecode_convert_class.cpp | 117 ++++++++++++++++++ 2 files changed, 119 insertions(+), 1 deletion(-) diff --git a/regression/cbmc-java/enum1/test.desc b/regression/cbmc-java/enum1/test.desc index d9ca7a162db..4c1fcafe076 100644 --- a/regression/cbmc-java/enum1/test.desc +++ b/regression/cbmc-java/enum1/test.desc @@ -1,7 +1,8 @@ CORE enum1.class --java-unwind-enum-static --unwind 3 -^EXIT=10$ +^VERIFICATION SUCCESSFUL$ +^EXIT=0$ ^SIGNAL=0$ ^Unwinding loop java::enum1.:\(\)V.0 iteration 5 \(6 max\) file enum1.java line 6 function java::enum1.:\(\)V bytecode_index 78 thread 0$ -- diff --git a/src/java_bytecode/java_bytecode_convert_class.cpp b/src/java_bytecode/java_bytecode_convert_class.cpp index 375e916dd3a..2926da79fc3 100644 --- a/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/src/java_bytecode/java_bytecode_convert_class.cpp @@ -16,6 +16,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "java_bytecode_convert_method.h" #include "java_bytecode_language.h" +#include #include #include @@ -359,6 +360,122 @@ void java_bytecode_convert_classt::add_array_types() symbol.is_type=true; symbol.type=struct_type; symbol_table.add(symbol); + + // Also provide a clone method: + // ---------------------------- + + const irep_idt clone_name= + id2string(symbol_type.get_identifier())+".clone:()Ljava/lang/Object;"; + code_typet clone_type; + clone_type.return_type()= + pointer_typet(symbol_typet("java::java.lang.Object")); + code_typet::parametert this_param; + this_param.set_identifier(id2string(clone_name)+"::this"); + this_param.set_base_name("this"); + this_param.set_this(); + this_param.type()=pointer_typet(symbol_type); + clone_type.parameters().push_back(this_param); + + parameter_symbolt this_symbol; + this_symbol.name=this_param.get_identifier(); + this_symbol.base_name=this_param.get_base_name(); + this_symbol.pretty_name=this_symbol.base_name; + this_symbol.type=this_param.type(); + this_symbol.mode=ID_java; + symbol_table.add(this_symbol); + + const irep_idt local_name= + id2string(clone_name)+"::cloned_array"; + auxiliary_symbolt local_symbol; + local_symbol.name=local_name; + local_symbol.base_name="cloned_array"; + local_symbol.pretty_name=local_symbol.base_name; + local_symbol.type=pointer_typet(symbol_type); + local_symbol.mode=ID_java; + symbol_table.add(local_symbol); + const auto &local_symexpr=local_symbol.symbol_expr(); + + code_blockt clone_body; + + code_declt declare_cloned(local_symexpr); + clone_body.move_to_operands(declare_cloned); + + side_effect_exprt java_new_array( + ID_java_new_array, + pointer_typet(symbol_type)); + dereference_exprt old_array(this_symbol.symbol_expr(), symbol_type); + dereference_exprt new_array(local_symexpr, symbol_type); + member_exprt old_length(old_array, comp1.get_name(), comp1.type()); + java_new_array.copy_to_operands(old_length); + code_assignt create_blank(local_symexpr, java_new_array); + clone_body.move_to_operands(create_blank); + + + member_exprt old_data(old_array, comp2.get_name(), comp2.type()); + member_exprt new_data(new_array, comp2.get_name(), comp2.type()); + + /* + // TODO use this instead of a loop. + codet array_copy; + array_copy.set_statement(ID_array_copy); + array_copy.move_to_operands(new_data); + array_copy.move_to_operands(old_data); + clone_body.move_to_operands(array_copy); + */ + + // Begin for-loop to replace: + + const irep_idt index_name= + id2string(clone_name)+"::index"; + auxiliary_symbolt index_symbol; + index_symbol.name=index_name; + index_symbol.base_name="index"; + index_symbol.pretty_name=index_symbol.base_name; + index_symbol.type=comp1.type(); + index_symbol.mode=ID_java; + symbol_table.add(index_symbol); + const auto &index_symexpr=index_symbol.symbol_expr(); + + code_declt declare_index(index_symexpr); + clone_body.move_to_operands(declare_index); + + code_fort copy_loop; + + copy_loop.init()= + code_assignt(index_symexpr, from_integer(0, index_symexpr.type())); + copy_loop.cond()= + binary_relation_exprt(index_symexpr, ID_lt, old_length); + + side_effect_exprt inc(ID_assign); + inc.operands().resize(2); + inc.op0()=index_symexpr; + inc.op1()=plus_exprt(index_symexpr, from_integer(1, index_symexpr.type())); + copy_loop.iter()=inc; + + dereference_exprt old_cell( + plus_exprt(old_data, index_symexpr), old_data.type().subtype()); + dereference_exprt new_cell( + plus_exprt(new_data, index_symexpr), new_data.type().subtype()); + code_assignt copy_cell(new_cell, old_cell); + copy_loop.body()=copy_cell; + + // End for-loop + clone_body.move_to_operands(copy_loop); + + member_exprt new_base_class(new_array, comp0.get_name(), comp0.type()); + address_of_exprt retval(new_base_class); + code_returnt return_inst(retval); + clone_body.move_to_operands(return_inst); + + symbolt clone_symbol; + clone_symbol.name=clone_name; + clone_symbol.pretty_name= + id2string(symbol_type.get_identifier())+".clone:()"; + clone_symbol.base_name="clone"; + clone_symbol.type=clone_type; + clone_symbol.value=clone_body; + clone_symbol.mode=ID_java; + symbol_table.add(clone_symbol); } } From ebaad56b73a7e9957539893c2c5095d6e4455b2f Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Thu, 6 Apr 2017 14:08:21 +0100 Subject: [PATCH 162/699] Remove blank lines from regression test specs Matching blank lines fails on Windows/AppVeyor. Also, there should not be any requirement for our output to contain blank lines. --- regression/acceleration/array_unsafe1/test.desc | 1 - regression/acceleration/array_unsafe2/test.desc | 1 - regression/acceleration/array_unsafe3/test.desc | 1 - regression/acceleration/array_unsafe4/test.desc | 1 - regression/acceleration/const_unsafe1/test.desc | 1 - regression/acceleration/diamond_unsafe1/test.desc | 1 - regression/acceleration/diamond_unsafe2/test.desc | 1 - regression/acceleration/functions_unsafe1/test.desc | 1 - regression/acceleration/multivar_unsafe1/test.desc | 1 - regression/acceleration/nested_unsafe1/test.desc | 1 - regression/acceleration/overflow_unsafe1/test.desc | 1 - regression/acceleration/phases_unsafe1/test.desc | 1 - regression/acceleration/simple_unsafe1/test.desc | 1 - regression/acceleration/simple_unsafe2/test.desc | 1 - regression/acceleration/simple_unsafe3/test.desc | 1 - regression/acceleration/simple_unsafe4/test.desc | 1 - regression/ansi-c/static_inline1/test.desc | 1 - regression/ansi-c/static_inline2/test.desc | 1 - regression/cbmc-incr-oneloop/unwind-forever1/test.desc | 1 - regression/cbmc-incr-oneloop/unwind-forever2/test.desc | 1 - regression/cbmc-java/tableswitch2/test.desc | 1 - regression/cpp-linter/function-comment-header1/test.desc | 1 - regression/cpp-linter/struct-inline-decl/test.desc | 1 - .../goto-analyzer/approx-array-variable-const-fp/test.desc | 1 - .../approx-const-fp-array-variable-cast-const-fp/test.desc | 1 - .../approx-const-fp-array-variable-const-fp-with-null/test.desc | 1 - .../approx-const-fp-array-variable-const-fp/test.desc | 1 - .../test.desc | 1 - .../test.desc | 1 - .../test.desc | 1 - .../test.desc | 1 - .../no-match-const-fp-array-literal-const-fp-run-time/test.desc | 1 - .../test.desc | 1 - .../no-match-const-fp-array-literal-non-const-fp/test.desc | 1 - .../goto-analyzer/no-match-const-fp-array-non-const-fp/test.desc | 1 - .../no-match-const-fp-binary-op-const-lost/test.desc | 1 - .../no-match-const-fp-const-array-index-lost/test.desc | 1 - .../goto-analyzer/no-match-const-fp-const-array-lost/test.desc | 1 - regression/goto-analyzer/no-match-const-fp-const-cast/test.desc | 1 - regression/goto-analyzer/no-match-const-fp-const-lost/test.desc | 1 - .../test.desc | 1 - .../test.desc | 1 - .../no-match-const-fp-dereference-const-pointer-null/test.desc | 1 - .../test.desc | 1 - .../no-match-const-fp-dynamic-array-non-const-fp/test.desc | 1 - .../test.desc | 1 - .../no-match-const-fp-non-const-struct-const-fp/test.desc | 1 - .../no-match-const-fp-non-const-struct-non-const-fp/test.desc | 1 - regression/goto-analyzer/no-match-const-fp-null/test.desc | 1 - .../no-match-const-fp-ternerary-op-const-lost/test.desc | 1 - .../test.desc | 1 - .../no-match-const-pointer-non-const-struct-const-fp/test.desc | 1 - .../no-match-const-struct-non-const-fp-null/test.desc | 1 - .../test.desc | 1 - .../test.desc | 1 - .../test.desc | 1 - regression/goto-analyzer/no-match-non-const-fp/test.desc | 1 - regression/goto-analyzer/no-match-parameter-const-fp/test.desc | 1 - regression/goto-analyzer/no-match-parameter-fp/test.desc | 1 - .../test.desc | 1 - .../precise-const-fp-array-literal-const-fp-run-time/test.desc | 1 - .../test.desc | 1 - .../test.desc | 1 - .../test.desc | 1 - .../test.desc | 1 - .../precise-const-fp-const-struct-non-const-fp/test.desc | 1 - .../test.desc | 1 - regression/goto-analyzer/precise-const-fp/test.desc | 1 - .../precise-const-pointer-const-struct-fp/test.desc | 1 - .../goto-analyzer/precise-const-struct-non-const-fp/test.desc | 1 - .../precise-derefence-const-pointer-const-fp/test.desc | 1 - regression/goto-analyzer/precise-derefence/test.desc | 1 - .../precise-dereference-address-pointer-const-fp/test.desc | 1 - .../test.desc | 1 - .../test.desc | 1 - .../precise-dereference-const-struct-pointer-const-fp/test.desc | 1 - .../approx-array-variable-const-fp-only-remove-const/test.desc | 1 - .../approx-array-variable-const-fp-remove-all-fp/test.desc | 1 - .../no-match-non-const-fp-only-remove-const/test.desc | 1 - .../no-match-non-const-fp-remove-all-fp/test.desc | 1 - .../goto-instrument/precise-const-fp-only-remove-const/test.desc | 1 - .../goto-instrument/precise-const-fp-remove-all-fp/test.desc | 1 - 82 files changed, 82 deletions(-) diff --git a/regression/acceleration/array_unsafe1/test.desc b/regression/acceleration/array_unsafe1/test.desc index 200554d997b..e6fe08aeb20 100644 --- a/regression/acceleration/array_unsafe1/test.desc +++ b/regression/acceleration/array_unsafe1/test.desc @@ -1,7 +1,6 @@ CORE main.c --no-unwinding-assertions - ^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ diff --git a/regression/acceleration/array_unsafe2/test.desc b/regression/acceleration/array_unsafe2/test.desc index 200554d997b..e6fe08aeb20 100644 --- a/regression/acceleration/array_unsafe2/test.desc +++ b/regression/acceleration/array_unsafe2/test.desc @@ -1,7 +1,6 @@ CORE main.c --no-unwinding-assertions - ^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ diff --git a/regression/acceleration/array_unsafe3/test.desc b/regression/acceleration/array_unsafe3/test.desc index 200554d997b..e6fe08aeb20 100644 --- a/regression/acceleration/array_unsafe3/test.desc +++ b/regression/acceleration/array_unsafe3/test.desc @@ -1,7 +1,6 @@ CORE main.c --no-unwinding-assertions - ^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ diff --git a/regression/acceleration/array_unsafe4/test.desc b/regression/acceleration/array_unsafe4/test.desc index 200554d997b..e6fe08aeb20 100644 --- a/regression/acceleration/array_unsafe4/test.desc +++ b/regression/acceleration/array_unsafe4/test.desc @@ -1,7 +1,6 @@ CORE main.c --no-unwinding-assertions - ^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ diff --git a/regression/acceleration/const_unsafe1/test.desc b/regression/acceleration/const_unsafe1/test.desc index 200554d997b..e6fe08aeb20 100644 --- a/regression/acceleration/const_unsafe1/test.desc +++ b/regression/acceleration/const_unsafe1/test.desc @@ -1,7 +1,6 @@ CORE main.c --no-unwinding-assertions - ^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ diff --git a/regression/acceleration/diamond_unsafe1/test.desc b/regression/acceleration/diamond_unsafe1/test.desc index 200554d997b..e6fe08aeb20 100644 --- a/regression/acceleration/diamond_unsafe1/test.desc +++ b/regression/acceleration/diamond_unsafe1/test.desc @@ -1,7 +1,6 @@ CORE main.c --no-unwinding-assertions - ^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ diff --git a/regression/acceleration/diamond_unsafe2/test.desc b/regression/acceleration/diamond_unsafe2/test.desc index 200554d997b..e6fe08aeb20 100644 --- a/regression/acceleration/diamond_unsafe2/test.desc +++ b/regression/acceleration/diamond_unsafe2/test.desc @@ -1,7 +1,6 @@ CORE main.c --no-unwinding-assertions - ^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ diff --git a/regression/acceleration/functions_unsafe1/test.desc b/regression/acceleration/functions_unsafe1/test.desc index 200554d997b..e6fe08aeb20 100644 --- a/regression/acceleration/functions_unsafe1/test.desc +++ b/regression/acceleration/functions_unsafe1/test.desc @@ -1,7 +1,6 @@ CORE main.c --no-unwinding-assertions - ^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ diff --git a/regression/acceleration/multivar_unsafe1/test.desc b/regression/acceleration/multivar_unsafe1/test.desc index 200554d997b..e6fe08aeb20 100644 --- a/regression/acceleration/multivar_unsafe1/test.desc +++ b/regression/acceleration/multivar_unsafe1/test.desc @@ -1,7 +1,6 @@ CORE main.c --no-unwinding-assertions - ^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ diff --git a/regression/acceleration/nested_unsafe1/test.desc b/regression/acceleration/nested_unsafe1/test.desc index 200554d997b..e6fe08aeb20 100644 --- a/regression/acceleration/nested_unsafe1/test.desc +++ b/regression/acceleration/nested_unsafe1/test.desc @@ -1,7 +1,6 @@ CORE main.c --no-unwinding-assertions - ^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ diff --git a/regression/acceleration/overflow_unsafe1/test.desc b/regression/acceleration/overflow_unsafe1/test.desc index 200554d997b..e6fe08aeb20 100644 --- a/regression/acceleration/overflow_unsafe1/test.desc +++ b/regression/acceleration/overflow_unsafe1/test.desc @@ -1,7 +1,6 @@ CORE main.c --no-unwinding-assertions - ^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ diff --git a/regression/acceleration/phases_unsafe1/test.desc b/regression/acceleration/phases_unsafe1/test.desc index 200554d997b..e6fe08aeb20 100644 --- a/regression/acceleration/phases_unsafe1/test.desc +++ b/regression/acceleration/phases_unsafe1/test.desc @@ -1,7 +1,6 @@ CORE main.c --no-unwinding-assertions - ^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ diff --git a/regression/acceleration/simple_unsafe1/test.desc b/regression/acceleration/simple_unsafe1/test.desc index 200554d997b..e6fe08aeb20 100644 --- a/regression/acceleration/simple_unsafe1/test.desc +++ b/regression/acceleration/simple_unsafe1/test.desc @@ -1,7 +1,6 @@ CORE main.c --no-unwinding-assertions - ^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ diff --git a/regression/acceleration/simple_unsafe2/test.desc b/regression/acceleration/simple_unsafe2/test.desc index 200554d997b..e6fe08aeb20 100644 --- a/regression/acceleration/simple_unsafe2/test.desc +++ b/regression/acceleration/simple_unsafe2/test.desc @@ -1,7 +1,6 @@ CORE main.c --no-unwinding-assertions - ^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ diff --git a/regression/acceleration/simple_unsafe3/test.desc b/regression/acceleration/simple_unsafe3/test.desc index 200554d997b..e6fe08aeb20 100644 --- a/regression/acceleration/simple_unsafe3/test.desc +++ b/regression/acceleration/simple_unsafe3/test.desc @@ -1,7 +1,6 @@ CORE main.c --no-unwinding-assertions - ^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ diff --git a/regression/acceleration/simple_unsafe4/test.desc b/regression/acceleration/simple_unsafe4/test.desc index 200554d997b..e6fe08aeb20 100644 --- a/regression/acceleration/simple_unsafe4/test.desc +++ b/regression/acceleration/simple_unsafe4/test.desc @@ -1,7 +1,6 @@ CORE main.c --no-unwinding-assertions - ^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ diff --git a/regression/ansi-c/static_inline1/test.desc b/regression/ansi-c/static_inline1/test.desc index 5717777037a..52168c7eba4 100644 --- a/regression/ansi-c/static_inline1/test.desc +++ b/regression/ansi-c/static_inline1/test.desc @@ -4,6 +4,5 @@ main.c ^EXIT=0$ ^SIGNAL=0$ ^VERIFICATION SUCCESSFUL$ - -- ^warning: ignoring diff --git a/regression/ansi-c/static_inline2/test.desc b/regression/ansi-c/static_inline2/test.desc index c5c5692745d..6a006f47021 100644 --- a/regression/ansi-c/static_inline2/test.desc +++ b/regression/ansi-c/static_inline2/test.desc @@ -4,6 +4,5 @@ main.c ^EXIT=0$ ^SIGNAL=0$ ^VERIFICATION SUCCESSFUL$ - -- ^warning: ignoring diff --git a/regression/cbmc-incr-oneloop/unwind-forever1/test.desc b/regression/cbmc-incr-oneloop/unwind-forever1/test.desc index 617547e56ad..5d03502707e 100644 --- a/regression/cbmc-incr-oneloop/unwind-forever1/test.desc +++ b/regression/cbmc-incr-oneloop/unwind-forever1/test.desc @@ -3,6 +3,5 @@ main.c --incremental-check main.0 ^EXIT=142$ ^SIGNAL=0$ - -- ^warning: ignoring diff --git a/regression/cbmc-incr-oneloop/unwind-forever2/test.desc b/regression/cbmc-incr-oneloop/unwind-forever2/test.desc index bff68c7e0c8..920f3890da5 100644 --- a/regression/cbmc-incr-oneloop/unwind-forever2/test.desc +++ b/regression/cbmc-incr-oneloop/unwind-forever2/test.desc @@ -3,6 +3,5 @@ main.c --incremental-check main.0 ^EXIT=142$ ^SIGNAL=0$ - -- ^warning: ignoring diff --git a/regression/cbmc-java/tableswitch2/test.desc b/regression/cbmc-java/tableswitch2/test.desc index b9e08d5d49b..baee77bb8e9 100644 --- a/regression/cbmc-java/tableswitch2/test.desc +++ b/regression/cbmc-java/tableswitch2/test.desc @@ -1,7 +1,6 @@ CORE table_switch_neg_offset.class --function table_switch_neg_offset.f - ^EXIT=0$ ^SIGNAL=0$ ^VERIFICATION SUCCESSFUL$ diff --git a/regression/cpp-linter/function-comment-header1/test.desc b/regression/cpp-linter/function-comment-header1/test.desc index efaae0b7391..708eecf0783 100644 --- a/regression/cpp-linter/function-comment-header1/test.desc +++ b/regression/cpp-linter/function-comment-header1/test.desc @@ -3,6 +3,5 @@ main.cpp ^main\.cpp:26: Could not find function header comment for foo \[readability/function_comment\] \[4\] ^Total errors found: 1$ - ^SIGNAL=0$ -- diff --git a/regression/cpp-linter/struct-inline-decl/test.desc b/regression/cpp-linter/struct-inline-decl/test.desc index 4a53c26c870..12418d892f4 100644 --- a/regression/cpp-linter/struct-inline-decl/test.desc +++ b/regression/cpp-linter/struct-inline-decl/test.desc @@ -1,7 +1,6 @@ CORE main.cpp - ^Total errors found: 0$ ^EXIT=0$ ^SIGNAL=0$ diff --git a/regression/goto-analyzer/approx-array-variable-const-fp/test.desc b/regression/goto-analyzer/approx-array-variable-const-fp/test.desc index 83a930d1c36..a0db9ddeaa9 100644 --- a/regression/goto-analyzer/approx-array-variable-const-fp/test.desc +++ b/regression/goto-analyzer/approx-array-variable-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp_tbl\[\(signed long int\)i\] == f2 THEN GOTO [0-9]$ ^\s*IF fp_tbl\[\(signed long int\)i\] == f3 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/approx-const-fp-array-variable-cast-const-fp/test.desc b/regression/goto-analyzer/approx-const-fp-array-variable-cast-const-fp/test.desc index a937e306d31..e6f1f4b5752 100644 --- a/regression/goto-analyzer/approx-const-fp-array-variable-cast-const-fp/test.desc +++ b/regression/goto-analyzer/approx-const-fp-array-variable-cast-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f2 THEN GOTO [0-9]$ ^\s*IF fp == f3 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/approx-const-fp-array-variable-const-fp-with-null/test.desc b/regression/goto-analyzer/approx-const-fp-array-variable-const-fp-with-null/test.desc index a937e306d31..e6f1f4b5752 100644 --- a/regression/goto-analyzer/approx-const-fp-array-variable-const-fp-with-null/test.desc +++ b/regression/goto-analyzer/approx-const-fp-array-variable-const-fp-with-null/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f2 THEN GOTO [0-9]$ ^\s*IF fp == f3 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/approx-const-fp-array-variable-const-fp/test.desc b/regression/goto-analyzer/approx-const-fp-array-variable-const-fp/test.desc index a937e306d31..e6f1f4b5752 100644 --- a/regression/goto-analyzer/approx-const-fp-array-variable-const-fp/test.desc +++ b/regression/goto-analyzer/approx-const-fp-array-variable-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f2 THEN GOTO [0-9]$ ^\s*IF fp == f3 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/approx-const-fp-array-variable-const-pointer-const-struct-non-const-fp/test.desc b/regression/goto-analyzer/approx-const-fp-array-variable-const-pointer-const-struct-non-const-fp/test.desc index a937e306d31..e6f1f4b5752 100644 --- a/regression/goto-analyzer/approx-const-fp-array-variable-const-pointer-const-struct-non-const-fp/test.desc +++ b/regression/goto-analyzer/approx-const-fp-array-variable-const-pointer-const-struct-non-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f2 THEN GOTO [0-9]$ ^\s*IF fp == f3 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/approx-const-fp-array-variable-const-struct-non-const-fp/test.desc b/regression/goto-analyzer/approx-const-fp-array-variable-const-struct-non-const-fp/test.desc index a937e306d31..e6f1f4b5752 100644 --- a/regression/goto-analyzer/approx-const-fp-array-variable-const-struct-non-const-fp/test.desc +++ b/regression/goto-analyzer/approx-const-fp-array-variable-const-struct-non-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f2 THEN GOTO [0-9]$ ^\s*IF fp == f3 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/approx-const-fp-array-variable-invalid-cast-const-fp/test.desc b/regression/goto-analyzer/approx-const-fp-array-variable-invalid-cast-const-fp/test.desc index 6df2697851a..661ac93a14f 100644 --- a/regression/goto-analyzer/approx-const-fp-array-variable-invalid-cast-const-fp/test.desc +++ b/regression/goto-analyzer/approx-const-fp-array-variable-invalid-cast-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == \(const void_fp\)f2 THEN GOTO [0-9]$ ^\s*IF fp == \(const void_fp\)f3 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-array-const-pointer-const-fp-const-lost/test.desc b/regression/goto-analyzer/no-match-const-array-const-pointer-const-fp-const-lost/test.desc index 9ac0520abde..cb389930278 100644 --- a/regression/goto-analyzer/no-match-const-array-const-pointer-const-fp-const-lost/test.desc +++ b/regression/goto-analyzer/no-match-const-array-const-pointer-const-fp-const-lost/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF \*fp == f1 THEN GOTO [0-9]$ ^\s*IF \*fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-fp-array-literal-const-fp-run-time/test.desc b/regression/goto-analyzer/no-match-const-fp-array-literal-const-fp-run-time/test.desc index 997ec886207..a73805f5730 100644 --- a/regression/goto-analyzer/no-match-const-fp-array-literal-const-fp-run-time/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-array-literal-const-fp-run-time/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f1 THEN GOTO [0-9]$ ^\s*IF fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp-run-time/test.desc b/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp-run-time/test.desc index 997ec886207..a73805f5730 100644 --- a/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp-run-time/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp-run-time/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f1 THEN GOTO [0-9]$ ^\s*IF fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp/test.desc b/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp/test.desc index 9c0926c2e7a..13d0c5353ce 100644 --- a/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp2 == f1 THEN GOTO [0-9]$ ^\s*IF fp2 == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-fp-array-non-const-fp/test.desc b/regression/goto-analyzer/no-match-const-fp-array-non-const-fp/test.desc index 9c0926c2e7a..13d0c5353ce 100644 --- a/regression/goto-analyzer/no-match-const-fp-array-non-const-fp/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-array-non-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp2 == f1 THEN GOTO [0-9]$ ^\s*IF fp2 == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-fp-binary-op-const-lost/test.desc b/regression/goto-analyzer/no-match-const-fp-binary-op-const-lost/test.desc index e8357d911c6..b9a72f79cfe 100644 --- a/regression/goto-analyzer/no-match-const-fp-binary-op-const-lost/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-binary-op-const-lost/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f1 THEN GOTO [0-9]$ ^\s*IF fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-fp-const-array-index-lost/test.desc b/regression/goto-analyzer/no-match-const-fp-const-array-index-lost/test.desc index 9ac0520abde..cb389930278 100644 --- a/regression/goto-analyzer/no-match-const-fp-const-array-index-lost/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-const-array-index-lost/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF \*fp == f1 THEN GOTO [0-9]$ ^\s*IF \*fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-fp-const-array-lost/test.desc b/regression/goto-analyzer/no-match-const-fp-const-array-lost/test.desc index 9ac0520abde..cb389930278 100644 --- a/regression/goto-analyzer/no-match-const-fp-const-array-lost/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-const-array-lost/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF \*fp == f1 THEN GOTO [0-9]$ ^\s*IF \*fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-fp-const-cast/test.desc b/regression/goto-analyzer/no-match-const-fp-const-cast/test.desc index e8357d911c6..b9a72f79cfe 100644 --- a/regression/goto-analyzer/no-match-const-fp-const-cast/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-const-cast/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f1 THEN GOTO [0-9]$ ^\s*IF fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-fp-const-lost/test.desc b/regression/goto-analyzer/no-match-const-fp-const-lost/test.desc index e8357d911c6..b9a72f79cfe 100644 --- a/regression/goto-analyzer/no-match-const-fp-const-lost/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-const-lost/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f1 THEN GOTO [0-9]$ ^\s*IF fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-fp-const-pointer-const-struct-const-fp-null/test.desc b/regression/goto-analyzer/no-match-const-fp-const-pointer-const-struct-const-fp-null/test.desc index 25b505c0a0f..4786993cade 100644 --- a/regression/goto-analyzer/no-match-const-fp-const-pointer-const-struct-const-fp-null/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-const-pointer-const-struct-const-fp-null/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*ASSERT FALSE // invalid function pointer$ ^SIGNAL=0$ diff --git a/regression/goto-analyzer/no-match-const-fp-const-pointer-non-const-struct-const-fp/test.desc b/regression/goto-analyzer/no-match-const-fp-const-pointer-non-const-struct-const-fp/test.desc index 997ec886207..a73805f5730 100644 --- a/regression/goto-analyzer/no-match-const-fp-const-pointer-non-const-struct-const-fp/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-const-pointer-non-const-struct-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f1 THEN GOTO [0-9]$ ^\s*IF fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-fp-dereference-const-pointer-null/test.desc b/regression/goto-analyzer/no-match-const-fp-dereference-const-pointer-null/test.desc index 25b505c0a0f..4786993cade 100644 --- a/regression/goto-analyzer/no-match-const-fp-dereference-const-pointer-null/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-dereference-const-pointer-null/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*ASSERT FALSE // invalid function pointer$ ^SIGNAL=0$ diff --git a/regression/goto-analyzer/no-match-const-fp-dereference-non-const-pointer-const-fp/test.desc b/regression/goto-analyzer/no-match-const-fp-dereference-non-const-pointer-const-fp/test.desc index 61a7ec29e6b..f7f42277bae 100644 --- a/regression/goto-analyzer/no-match-const-fp-dereference-non-const-pointer-const-fp/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-dereference-non-const-pointer-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF final_fp == f1 THEN GOTO [0-9]$ ^\s*IF final_fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-fp-dynamic-array-non-const-fp/test.desc b/regression/goto-analyzer/no-match-const-fp-dynamic-array-non-const-fp/test.desc index 997ec886207..a73805f5730 100644 --- a/regression/goto-analyzer/no-match-const-fp-dynamic-array-non-const-fp/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-dynamic-array-non-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f1 THEN GOTO [0-9]$ ^\s*IF fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-fp-non-const-pointer-non-const-struct-const-fp/test.desc b/regression/goto-analyzer/no-match-const-fp-non-const-pointer-non-const-struct-const-fp/test.desc index 997ec886207..a73805f5730 100644 --- a/regression/goto-analyzer/no-match-const-fp-non-const-pointer-non-const-struct-const-fp/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-non-const-pointer-non-const-struct-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f1 THEN GOTO [0-9]$ ^\s*IF fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-fp-non-const-struct-const-fp/test.desc b/regression/goto-analyzer/no-match-const-fp-non-const-struct-const-fp/test.desc index 997ec886207..a73805f5730 100644 --- a/regression/goto-analyzer/no-match-const-fp-non-const-struct-const-fp/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-non-const-struct-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f1 THEN GOTO [0-9]$ ^\s*IF fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-fp-non-const-struct-non-const-fp/test.desc b/regression/goto-analyzer/no-match-const-fp-non-const-struct-non-const-fp/test.desc index 997ec886207..a73805f5730 100644 --- a/regression/goto-analyzer/no-match-const-fp-non-const-struct-non-const-fp/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-non-const-struct-non-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f1 THEN GOTO [0-9]$ ^\s*IF fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-fp-null/test.desc b/regression/goto-analyzer/no-match-const-fp-null/test.desc index 267ec2284f7..d8e8d833238 100644 --- a/regression/goto-analyzer/no-match-const-fp-null/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-null/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*ASSERT FALSE // invalid function pointer$ -- diff --git a/regression/goto-analyzer/no-match-const-fp-ternerary-op-const-lost/test.desc b/regression/goto-analyzer/no-match-const-fp-ternerary-op-const-lost/test.desc index e8357d911c6..b9a72f79cfe 100644 --- a/regression/goto-analyzer/no-match-const-fp-ternerary-op-const-lost/test.desc +++ b/regression/goto-analyzer/no-match-const-fp-ternerary-op-const-lost/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f1 THEN GOTO [0-9]$ ^\s*IF fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-pointer-const-struct-const-fp-const-cast/test.desc b/regression/goto-analyzer/no-match-const-pointer-const-struct-const-fp-const-cast/test.desc index 2f4b2832b4d..4e6fda43498 100644 --- a/regression/goto-analyzer/no-match-const-pointer-const-struct-const-fp-const-cast/test.desc +++ b/regression/goto-analyzer/no-match-const-pointer-const-struct-const-fp-const-cast/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF container_pointer->fp == f1 THEN GOTO [0-9]$ ^\s*IF container_pointer->fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-pointer-non-const-struct-const-fp/test.desc b/regression/goto-analyzer/no-match-const-pointer-non-const-struct-const-fp/test.desc index 2760fadd576..eaad08aafe0 100644 --- a/regression/goto-analyzer/no-match-const-pointer-non-const-struct-const-fp/test.desc +++ b/regression/goto-analyzer/no-match-const-pointer-non-const-struct-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF pts->go == f1 THEN GOTO [0-9]$ ^\s*IF pts->go == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-const-struct-non-const-fp-null/test.desc b/regression/goto-analyzer/no-match-const-struct-non-const-fp-null/test.desc index 25b505c0a0f..4786993cade 100644 --- a/regression/goto-analyzer/no-match-const-struct-non-const-fp-null/test.desc +++ b/regression/goto-analyzer/no-match-const-struct-non-const-fp-null/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*ASSERT FALSE // invalid function pointer$ ^SIGNAL=0$ diff --git a/regression/goto-analyzer/no-match-dereference-const-pointer-const-array-literal-pointer-const-fp/test.desc b/regression/goto-analyzer/no-match-dereference-const-pointer-const-array-literal-pointer-const-fp/test.desc index 7e0aca75523..9c63fcd4c03 100644 --- a/regression/goto-analyzer/no-match-dereference-const-pointer-const-array-literal-pointer-const-fp/test.desc +++ b/regression/goto-analyzer/no-match-dereference-const-pointer-const-array-literal-pointer-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f1 THEN GOTO [0-9]$ ^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-dereference-non-const-struct-const-pointer-const-fp/test.desc b/regression/goto-analyzer/no-match-dereference-non-const-struct-const-pointer-const-fp/test.desc index f55defde97b..662bd323844 100644 --- a/regression/goto-analyzer/no-match-dereference-non-const-struct-const-pointer-const-fp/test.desc +++ b/regression/goto-analyzer/no-match-dereference-non-const-struct-const-pointer-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF \*container_container\.container == f1 THEN GOTO [0-9]$ ^\s*IF \*container_container\.container == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-dereference-non-const-struct-non-const-pointer-const-fp/test.desc b/regression/goto-analyzer/no-match-dereference-non-const-struct-non-const-pointer-const-fp/test.desc index f55defde97b..662bd323844 100644 --- a/regression/goto-analyzer/no-match-dereference-non-const-struct-non-const-pointer-const-fp/test.desc +++ b/regression/goto-analyzer/no-match-dereference-non-const-struct-non-const-pointer-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF \*container_container\.container == f1 THEN GOTO [0-9]$ ^\s*IF \*container_container\.container == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-non-const-fp/test.desc b/regression/goto-analyzer/no-match-non-const-fp/test.desc index 997ec886207..a73805f5730 100644 --- a/regression/goto-analyzer/no-match-non-const-fp/test.desc +++ b/regression/goto-analyzer/no-match-non-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f1 THEN GOTO [0-9]$ ^\s*IF fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-parameter-const-fp/test.desc b/regression/goto-analyzer/no-match-parameter-const-fp/test.desc index 997ec886207..a73805f5730 100644 --- a/regression/goto-analyzer/no-match-parameter-const-fp/test.desc +++ b/regression/goto-analyzer/no-match-parameter-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f1 THEN GOTO [0-9]$ ^\s*IF fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-parameter-fp/test.desc b/regression/goto-analyzer/no-match-parameter-fp/test.desc index 997ec886207..a73805f5730 100644 --- a/regression/goto-analyzer/no-match-parameter-fp/test.desc +++ b/regression/goto-analyzer/no-match-parameter-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF fp == f1 THEN GOTO [0-9]$ ^\s*IF fp == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/no-match-pointer-const-struct-array-literal-non-const-fp/test.desc b/regression/goto-analyzer/no-match-pointer-const-struct-array-literal-non-const-fp/test.desc index 83a4d98d9f4..24a5ab5ddda 100644 --- a/regression/goto-analyzer/no-match-pointer-const-struct-array-literal-non-const-fp/test.desc +++ b/regression/goto-analyzer/no-match-pointer-const-struct-array-literal-non-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f1 THEN GOTO [0-9]$ ^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f2 THEN GOTO [0-9]$ diff --git a/regression/goto-analyzer/precise-const-fp-array-literal-const-fp-run-time/test.desc b/regression/goto-analyzer/precise-const-fp-array-literal-const-fp-run-time/test.desc index 6c7de56a1a0..ab2a0acefba 100644 --- a/regression/goto-analyzer/precise-const-fp-array-literal-const-fp-run-time/test.desc +++ b/regression/goto-analyzer/precise-const-fp-array-literal-const-fp-run-time/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*f3\(\);$ -- diff --git a/regression/goto-analyzer/precise-const-fp-array-literal-const-struct-non-const-fp/test.desc b/regression/goto-analyzer/precise-const-fp-array-literal-const-struct-non-const-fp/test.desc index 2eff811f4bc..fad0e6c7a1d 100644 --- a/regression/goto-analyzer/precise-const-fp-array-literal-const-struct-non-const-fp/test.desc +++ b/regression/goto-analyzer/precise-const-fp-array-literal-const-struct-non-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*f3\(\);$ ^SIGNAL=0$ diff --git a/regression/goto-analyzer/precise-const-fp-array-variable-const-pointer-const-struct-non-const-fp/test.desc b/regression/goto-analyzer/precise-const-fp-array-variable-const-pointer-const-struct-non-const-fp/test.desc index eb1e2781ef1..90cd2485ce1 100644 --- a/regression/goto-analyzer/precise-const-fp-array-variable-const-pointer-const-struct-non-const-fp/test.desc +++ b/regression/goto-analyzer/precise-const-fp-array-variable-const-pointer-const-struct-non-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*f2\(\); ^SIGNAL=0$ diff --git a/regression/goto-analyzer/precise-const-fp-const-struct-const-array-literal-fp/test.desc b/regression/goto-analyzer/precise-const-fp-const-struct-const-array-literal-fp/test.desc index 2eff811f4bc..fad0e6c7a1d 100644 --- a/regression/goto-analyzer/precise-const-fp-const-struct-const-array-literal-fp/test.desc +++ b/regression/goto-analyzer/precise-const-fp-const-struct-const-array-literal-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*f3\(\);$ ^SIGNAL=0$ diff --git a/regression/goto-analyzer/precise-const-fp-const-struct-non-const-array-literal-fp/test.desc b/regression/goto-analyzer/precise-const-fp-const-struct-non-const-array-literal-fp/test.desc index 2eff811f4bc..fad0e6c7a1d 100644 --- a/regression/goto-analyzer/precise-const-fp-const-struct-non-const-array-literal-fp/test.desc +++ b/regression/goto-analyzer/precise-const-fp-const-struct-non-const-array-literal-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*f3\(\);$ ^SIGNAL=0$ diff --git a/regression/goto-analyzer/precise-const-fp-const-struct-non-const-fp/test.desc b/regression/goto-analyzer/precise-const-fp-const-struct-non-const-fp/test.desc index eb1e2781ef1..90cd2485ce1 100644 --- a/regression/goto-analyzer/precise-const-fp-const-struct-non-const-fp/test.desc +++ b/regression/goto-analyzer/precise-const-fp-const-struct-non-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*f2\(\); ^SIGNAL=0$ diff --git a/regression/goto-analyzer/precise-const-fp-dereference-const-pointer-const-fp/test.desc b/regression/goto-analyzer/precise-const-fp-dereference-const-pointer-const-fp/test.desc index 2eff811f4bc..fad0e6c7a1d 100644 --- a/regression/goto-analyzer/precise-const-fp-dereference-const-pointer-const-fp/test.desc +++ b/regression/goto-analyzer/precise-const-fp-dereference-const-pointer-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*f3\(\);$ ^SIGNAL=0$ diff --git a/regression/goto-analyzer/precise-const-fp/test.desc b/regression/goto-analyzer/precise-const-fp/test.desc index ef4cf690b60..4dd6e7fd098 100644 --- a/regression/goto-analyzer/precise-const-fp/test.desc +++ b/regression/goto-analyzer/precise-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*f2\(\); -- diff --git a/regression/goto-analyzer/precise-const-pointer-const-struct-fp/test.desc b/regression/goto-analyzer/precise-const-pointer-const-struct-fp/test.desc index 0de6942ba42..40361f6ccc2 100644 --- a/regression/goto-analyzer/precise-const-pointer-const-struct-fp/test.desc +++ b/regression/goto-analyzer/precise-const-pointer-const-struct-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*f2\(\);$ ^SIGNAL=0$ diff --git a/regression/goto-analyzer/precise-const-struct-non-const-fp/test.desc b/regression/goto-analyzer/precise-const-struct-non-const-fp/test.desc index eb1e2781ef1..90cd2485ce1 100644 --- a/regression/goto-analyzer/precise-const-struct-non-const-fp/test.desc +++ b/regression/goto-analyzer/precise-const-struct-non-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*f2\(\); ^SIGNAL=0$ diff --git a/regression/goto-analyzer/precise-derefence-const-pointer-const-fp/test.desc b/regression/goto-analyzer/precise-derefence-const-pointer-const-fp/test.desc index 2eff811f4bc..fad0e6c7a1d 100644 --- a/regression/goto-analyzer/precise-derefence-const-pointer-const-fp/test.desc +++ b/regression/goto-analyzer/precise-derefence-const-pointer-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*f3\(\);$ ^SIGNAL=0$ diff --git a/regression/goto-analyzer/precise-derefence/test.desc b/regression/goto-analyzer/precise-derefence/test.desc index ef4cf690b60..4dd6e7fd098 100644 --- a/regression/goto-analyzer/precise-derefence/test.desc +++ b/regression/goto-analyzer/precise-derefence/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*f2\(\); -- diff --git a/regression/goto-analyzer/precise-dereference-address-pointer-const-fp/test.desc b/regression/goto-analyzer/precise-dereference-address-pointer-const-fp/test.desc index 2eff811f4bc..fad0e6c7a1d 100644 --- a/regression/goto-analyzer/precise-dereference-address-pointer-const-fp/test.desc +++ b/regression/goto-analyzer/precise-dereference-address-pointer-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*f3\(\);$ ^SIGNAL=0$ diff --git a/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-fp/test.desc b/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-fp/test.desc index 2eff811f4bc..fad0e6c7a1d 100644 --- a/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-fp/test.desc +++ b/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*f3\(\);$ ^SIGNAL=0$ diff --git a/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-struct-const-fp/test.desc b/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-struct-const-fp/test.desc index 2eff811f4bc..fad0e6c7a1d 100644 --- a/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-struct-const-fp/test.desc +++ b/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-struct-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*f3\(\);$ ^SIGNAL=0$ diff --git a/regression/goto-analyzer/precise-dereference-const-struct-pointer-const-fp/test.desc b/regression/goto-analyzer/precise-dereference-const-struct-pointer-const-fp/test.desc index 2eff811f4bc..fad0e6c7a1d 100644 --- a/regression/goto-analyzer/precise-dereference-const-struct-pointer-const-fp/test.desc +++ b/regression/goto-analyzer/precise-dereference-const-struct-pointer-const-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check - ^Removing function pointers and virtual functions$ ^\s*f3\(\);$ ^SIGNAL=0$ diff --git a/regression/goto-instrument/approx-array-variable-const-fp-only-remove-const/test.desc b/regression/goto-instrument/approx-array-variable-const-fp-only-remove-const/test.desc index f58b03a58b3..83e4f545415 100644 --- a/regression/goto-instrument/approx-array-variable-const-fp-only-remove-const/test.desc +++ b/regression/goto-instrument/approx-array-variable-const-fp-only-remove-const/test.desc @@ -1,7 +1,6 @@ CORE main.c --verbosity 10 --pointer-check --remove-const-function-pointers - ^\s*IF fp_tbl\[\(signed long int\)i\] == f2 THEN GOTO [0-9]$ ^\s*IF fp_tbl\[\(signed long int\)i\] == f3 THEN GOTO [0-9]$ ^\s*IF fp_tbl\[\(signed long int\)i\] == f4 THEN GOTO [0-9]$ diff --git a/regression/goto-instrument/approx-array-variable-const-fp-remove-all-fp/test.desc b/regression/goto-instrument/approx-array-variable-const-fp-remove-all-fp/test.desc index 3d065f1a742..35ed94ae046 100644 --- a/regression/goto-instrument/approx-array-variable-const-fp-remove-all-fp/test.desc +++ b/regression/goto-instrument/approx-array-variable-const-fp-remove-all-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --verbosity 10 --pointer-check --remove-function-pointers - ^\s*IF fp_tbl\[\(signed long int\)i\] == f2 THEN GOTO [0-9]$ ^\s*IF fp_tbl\[\(signed long int\)i\] == f3 THEN GOTO [0-9]$ ^\s*IF fp_tbl\[\(signed long int\)i\] == f4 THEN GOTO [0-9]$ diff --git a/regression/goto-instrument/no-match-non-const-fp-only-remove-const/test.desc b/regression/goto-instrument/no-match-non-const-fp-only-remove-const/test.desc index 3b016907a44..9c23726e83c 100644 --- a/regression/goto-instrument/no-match-non-const-fp-only-remove-const/test.desc +++ b/regression/goto-instrument/no-match-non-const-fp-only-remove-const/test.desc @@ -1,7 +1,6 @@ CORE main.c --verbosity 10 --pointer-check --remove-const-function-pointers - ^\s*fp\(\);$ ^SIGNAL=0$ -- diff --git a/regression/goto-instrument/no-match-non-const-fp-remove-all-fp/test.desc b/regression/goto-instrument/no-match-non-const-fp-remove-all-fp/test.desc index 3190d348aae..46c2f8cd2d4 100644 --- a/regression/goto-instrument/no-match-non-const-fp-remove-all-fp/test.desc +++ b/regression/goto-instrument/no-match-non-const-fp-remove-all-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --verbosity 10 --pointer-check --remove-function-pointers - ^\s*IF fp == f1 THEN GOTO [0-9]$ ^\s*IF fp == f2 THEN GOTO [0-9]$ ^\s*IF fp == f3 THEN GOTO [0-9]$ diff --git a/regression/goto-instrument/precise-const-fp-only-remove-const/test.desc b/regression/goto-instrument/precise-const-fp-only-remove-const/test.desc index 2304d56b239..cdf49005c0b 100644 --- a/regression/goto-instrument/precise-const-fp-only-remove-const/test.desc +++ b/regression/goto-instrument/precise-const-fp-only-remove-const/test.desc @@ -1,7 +1,6 @@ CORE main.c --verbosity 10 --pointer-check --remove-const-function-pointers - ^\s*f2\(\); -- ^warning: ignoring diff --git a/regression/goto-instrument/precise-const-fp-remove-all-fp/test.desc b/regression/goto-instrument/precise-const-fp-remove-all-fp/test.desc index dd072b1c232..a559b2b1747 100644 --- a/regression/goto-instrument/precise-const-fp-remove-all-fp/test.desc +++ b/regression/goto-instrument/precise-const-fp-remove-all-fp/test.desc @@ -1,7 +1,6 @@ CORE main.c --verbosity 10 --pointer-check --remove-function-pointers - ^\s*f2\(\); -- ^warning: ignoring From b4658eb76b31151d3d2c18648a5caf1518c649cc Mon Sep 17 00:00:00 2001 From: Vojtech Forejt Date: Thu, 6 Apr 2017 17:19:18 +0100 Subject: [PATCH 163/699] Allow long long int instead of just long int in regexp of some tests. This prevents spurious test failures on Windows. Fixes #769. --- .../approx-array-variable-const-fp/test.desc | 18 +++++++++--------- .../test.desc | 18 +++++++++--------- .../test.desc | 18 +++++++++--------- .../test.desc | 18 +++++++++--------- .../test.desc | 18 +++++++++--------- 5 files changed, 45 insertions(+), 45 deletions(-) diff --git a/regression/goto-analyzer/approx-array-variable-const-fp/test.desc b/regression/goto-analyzer/approx-array-variable-const-fp/test.desc index a0db9ddeaa9..38027f70600 100644 --- a/regression/goto-analyzer/approx-array-variable-const-fp/test.desc +++ b/regression/goto-analyzer/approx-array-variable-const-fp/test.desc @@ -2,15 +2,15 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check ^Removing function pointers and virtual functions$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f2 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f3 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f4 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f2 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f3 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f4 THEN GOTO [0-9]$ ^SIGNAL=0$ -- -^\s*IF fp_tbl\[\(signed long int\)i\] == f1 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f5 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f6 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f7 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f8 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f9 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f1 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f5 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f6 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f7 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f8 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f9 THEN GOTO [0-9]$ ^warning: ignoring diff --git a/regression/goto-analyzer/no-match-dereference-const-pointer-const-array-literal-pointer-const-fp/test.desc b/regression/goto-analyzer/no-match-dereference-const-pointer-const-array-literal-pointer-const-fp/test.desc index 9c63fcd4c03..ef491f67113 100644 --- a/regression/goto-analyzer/no-match-dereference-const-pointer-const-array-literal-pointer-const-fp/test.desc +++ b/regression/goto-analyzer/no-match-dereference-const-pointer-const-array-literal-pointer-const-fp/test.desc @@ -2,15 +2,15 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check ^Removing function pointers and virtual functions$ -^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f1 THEN GOTO [0-9]$ -^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f2 THEN GOTO [0-9]$ -^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f3 THEN GOTO [0-9]$ -^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f4 THEN GOTO [0-9]$ -^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f5 THEN GOTO [0-9]$ -^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f6 THEN GOTO [0-9]$ -^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f7 THEN GOTO [0-9]$ -^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f8 THEN GOTO [0-9]$ -^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f9 THEN GOTO [0-9]$ +^\s*IF \*container_ptr->fp_tbl\[\(signed (long )*long int\)1\] == f1 THEN GOTO [0-9]$ +^\s*IF \*container_ptr->fp_tbl\[\(signed (long )*long int\)1\] == f2 THEN GOTO [0-9]$ +^\s*IF \*container_ptr->fp_tbl\[\(signed (long )*long int\)1\] == f3 THEN GOTO [0-9]$ +^\s*IF \*container_ptr->fp_tbl\[\(signed (long )*long int\)1\] == f4 THEN GOTO [0-9]$ +^\s*IF \*container_ptr->fp_tbl\[\(signed (long )*long int\)1\] == f5 THEN GOTO [0-9]$ +^\s*IF \*container_ptr->fp_tbl\[\(signed (long )*long int\)1\] == f6 THEN GOTO [0-9]$ +^\s*IF \*container_ptr->fp_tbl\[\(signed (long )*long int\)1\] == f7 THEN GOTO [0-9]$ +^\s*IF \*container_ptr->fp_tbl\[\(signed (long )*long int\)1\] == f8 THEN GOTO [0-9]$ +^\s*IF \*container_ptr->fp_tbl\[\(signed (long )*long int\)1\] == f9 THEN GOTO [0-9]$ ^SIGNAL=0$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/no-match-pointer-const-struct-array-literal-non-const-fp/test.desc b/regression/goto-analyzer/no-match-pointer-const-struct-array-literal-non-const-fp/test.desc index 24a5ab5ddda..a85714b51a1 100644 --- a/regression/goto-analyzer/no-match-pointer-const-struct-array-literal-non-const-fp/test.desc +++ b/regression/goto-analyzer/no-match-pointer-const-struct-array-literal-non-const-fp/test.desc @@ -2,15 +2,15 @@ CORE main.c --show-goto-functions --verbosity 10 --pointer-check ^Removing function pointers and virtual functions$ -^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f1 THEN GOTO [0-9]$ -^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f2 THEN GOTO [0-9]$ -^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f3 THEN GOTO [0-9]$ -^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f4 THEN GOTO [0-9]$ -^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f5 THEN GOTO [0-9]$ -^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f6 THEN GOTO [0-9]$ -^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f7 THEN GOTO [0-9]$ -^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f8 THEN GOTO [0-9]$ -^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f9 THEN GOTO [0-9]$ +^\s*IF container_ptr->fp_tbl\[\(signed (long )*long int\)1\] == f1 THEN GOTO [0-9]$ +^\s*IF container_ptr->fp_tbl\[\(signed (long )*long int\)1\] == f2 THEN GOTO [0-9]$ +^\s*IF container_ptr->fp_tbl\[\(signed (long )*long int\)1\] == f3 THEN GOTO [0-9]$ +^\s*IF container_ptr->fp_tbl\[\(signed (long )*long int\)1\] == f4 THEN GOTO [0-9]$ +^\s*IF container_ptr->fp_tbl\[\(signed (long )*long int\)1\] == f5 THEN GOTO [0-9]$ +^\s*IF container_ptr->fp_tbl\[\(signed (long )*long int\)1\] == f6 THEN GOTO [0-9]$ +^\s*IF container_ptr->fp_tbl\[\(signed (long )*long int\)1\] == f7 THEN GOTO [0-9]$ +^\s*IF container_ptr->fp_tbl\[\(signed (long )*long int\)1\] == f8 THEN GOTO [0-9]$ +^\s*IF container_ptr->fp_tbl\[\(signed (long )*long int\)1\] == f9 THEN GOTO [0-9]$ ^SIGNAL=0$ -- ^warning: ignoring diff --git a/regression/goto-instrument/approx-array-variable-const-fp-only-remove-const/test.desc b/regression/goto-instrument/approx-array-variable-const-fp-only-remove-const/test.desc index 83e4f545415..bc553fa5a0f 100644 --- a/regression/goto-instrument/approx-array-variable-const-fp-only-remove-const/test.desc +++ b/regression/goto-instrument/approx-array-variable-const-fp-only-remove-const/test.desc @@ -1,15 +1,15 @@ CORE main.c --verbosity 10 --pointer-check --remove-const-function-pointers -^\s*IF fp_tbl\[\(signed long int\)i\] == f2 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f3 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f4 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f2 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f3 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f4 THEN GOTO [0-9]$ ^SIGNAL=0$ -- -^\s*IF fp_tbl\[\(signed long int\)i\] == f1 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f5 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f6 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f7 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f8 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f9 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f1 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f5 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f6 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f7 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f8 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f9 THEN GOTO [0-9]$ ^warning: ignoring diff --git a/regression/goto-instrument/approx-array-variable-const-fp-remove-all-fp/test.desc b/regression/goto-instrument/approx-array-variable-const-fp-remove-all-fp/test.desc index 35ed94ae046..e9ede02a296 100644 --- a/regression/goto-instrument/approx-array-variable-const-fp-remove-all-fp/test.desc +++ b/regression/goto-instrument/approx-array-variable-const-fp-remove-all-fp/test.desc @@ -1,15 +1,15 @@ CORE main.c --verbosity 10 --pointer-check --remove-function-pointers -^\s*IF fp_tbl\[\(signed long int\)i\] == f2 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f3 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f4 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f2 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f3 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f4 THEN GOTO [0-9]$ ^SIGNAL=0$ -- -^\s*IF fp_tbl\[\(signed long int\)i\] == f1 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f5 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f6 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f7 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f8 THEN GOTO [0-9]$ -^\s*IF fp_tbl\[\(signed long int\)i\] == f9 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f1 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f5 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f6 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f7 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f8 THEN GOTO [0-9]$ +^\s*IF fp_tbl\[\(signed (long )*long int\)i\] == f9 THEN GOTO [0-9]$ ^warning: ignoring From a2f4ab3bfaf1a35e1674addaf6d1c0ead07b00ed Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 7 Apr 2017 15:49:55 +0100 Subject: [PATCH 164/699] Coverage (branch mode): add missing is-current-function test (#781) With `--cover-function-only`, all coverage tests should be conditional on the function containing the target matching `--function`; however this particular case got missed out. --- src/goto-instrument/cover.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index 3c69cd3efef..4d599fafef3 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -1411,7 +1411,7 @@ void instrument_cover_goals( t->source_location.set_function(i_it->function); } - if(i_it->is_goto() && !i_it->guard.is_true()) + if(i_it->is_goto() && !i_it->guard.is_true() && cover_curr_function) { std::string b=std::to_string(basic_blocks[i_it]); std::string true_comment= From 158d950226593765e68959574b4138d2c1f544e1 Mon Sep 17 00:00:00 2001 From: Vojtech Forejt Date: Fri, 7 Apr 2017 16:16:40 +0100 Subject: [PATCH 165/699] Speed up OSX builds on Travis. Do not autoupdate Homebrew, and limit cache size to 1G. --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 54078b93f76..a2396927dab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,8 +24,9 @@ matrix: before_install: #we create symlink to non-ccache gcc, to be used in tests - mkdir bin ; ln -s /usr/bin/gcc bin/gcc - - brew install ccache + - HOMEBREW_NO_AUTO_UPDATE=1 brew install ccache - export PATH=/usr/local/opt/ccache/libexec:$PATH + - ccache -M 1G env: COMPILER=g++ # OS X using clang++ @@ -34,11 +35,12 @@ matrix: compiler: clang cache: ccache before_install: - - brew install ccache + - HOMEBREW_NO_AUTO_UPDATE=1 brew install ccache - export PATH=/usr/local/opt/ccache/libexec:$PATH env: - COMPILER="ccache clang++ -Qunused-arguments -fcolor-diagnostics" - CCACHE_CPP2=yes + - ccache -M 1G # Ubuntu Linux with glibc using g++-5 - os: linux From 46151843eb88fba6ef5243da2d23441ff510bdae Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 10 Apr 2017 10:48:47 +0100 Subject: [PATCH 166/699] Restore array skip-initialize flag This allows a java-new-array instruction to indicate that the array will be completely initialized immediately afterwards, and therefore the zero-init instruction can be omitted. The nondet object factory currently uses this to note that it will non-det initialize the whole array. --- src/goto-programs/builtin_functions.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/goto-programs/builtin_functions.cpp b/src/goto-programs/builtin_functions.cpp index 359c25dc270..d5e27615d3d 100644 --- a/src/goto-programs/builtin_functions.cpp +++ b/src/goto-programs/builtin_functions.cpp @@ -837,17 +837,20 @@ void goto_convertt::do_java_new_array( t_p->source_location=location; // zero-initialize the data - exprt zero_element= - zero_initializer( - data.type().subtype(), - location, - ns, - get_message_handler()); - codet array_set(ID_array_set); - array_set.copy_to_operands(data, zero_element); - goto_programt::targett t_d=dest.add_instruction(OTHER); - t_d->code=array_set; - t_d->source_location=location; + if(!rhs.get_bool(ID_skip_initialize)) + { + exprt zero_element= + zero_initializer( + data.type().subtype(), + location, + ns, + get_message_handler()); + codet array_set(ID_array_set); + array_set.copy_to_operands(data, zero_element); + goto_programt::targett t_d=dest.add_instruction(OTHER); + t_d->code=array_set; + t_d->source_location=location; + } // multi-dimensional? From 44041aeff5ca8d2e69b4167222ed6dac86f0e009 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Mon, 10 Apr 2017 11:00:02 +0100 Subject: [PATCH 167/699] Allowing some options for string refinement We allow setting the options refine-arrays, refine-arithmetic and max-node-refinement options in the string solver. Not setting the refine-arrays option can greatly improve performances. --- src/cbmc/cbmc_solvers.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/cbmc/cbmc_solvers.cpp b/src/cbmc/cbmc_solvers.cpp index dace046cc17..b647ba17f52 100644 --- a/src/cbmc/cbmc_solvers.cpp +++ b/src/cbmc/cbmc_solvers.cpp @@ -242,6 +242,15 @@ cbmc_solverst::solvert* cbmc_solverst::get_string_refinement() if(options.get_bool_option("string-printable")) string_refinement->enforce_printable_characters(); + if(options.get_option("max-node-refinement")!="") + string_refinement->max_node_refinement= + options.get_unsigned_int_option("max-node-refinement"); + + string_refinement->do_array_refinement= + options.get_bool_option("refine-arrays"); + string_refinement->do_arithmetic_refinement= + options.get_bool_option("refine-arithmetic"); + return new solvert(string_refinement, prop); } From 7e1b38208db2fa3cd646c04ffb43cf2942f4b3e3 Mon Sep 17 00:00:00 2001 From: Cristina Date: Mon, 10 Apr 2017 13:54:35 +0100 Subject: [PATCH 168/699] Set function member for class identifier assignment --- src/goto-programs/remove_instanceof.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/goto-programs/remove_instanceof.cpp b/src/goto-programs/remove_instanceof.cpp index 3fc2699ef47..8e6c9f5de20 100644 --- a/src/goto-programs/remove_instanceof.cpp +++ b/src/goto-programs/remove_instanceof.cpp @@ -140,6 +140,7 @@ void remove_instanceoft::lower_instanceof( newinst->make_assignment(); newinst->code=code_assignt(newsym.symbol_expr(), object_clsid); newinst->source_location=this_inst->source_location; + newinst->function=this_inst->function; // Insert the check instruction after the existing one. // This will briefly be ill-formed (use before def of From 3cb035e4d6e441c85d8499db87049389a74b431e Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Tue, 11 Apr 2017 09:54:57 +0200 Subject: [PATCH 169/699] Fix style to silence cpplint --- src/java_bytecode/java_entry_point.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/java_bytecode/java_entry_point.cpp b/src/java_bytecode/java_entry_point.cpp index e504441bae6..3e4de0cdea5 100644 --- a/src/java_bytecode/java_entry_point.cpp +++ b/src/java_bytecode/java_entry_point.cpp @@ -194,8 +194,7 @@ bool java_static_lifetime_init( { it->second.symbol_expr(), class_symbol.type.get_bool(ID_enumeration) - } - ); + }); } } From 2fc6f099d5c5dba5e502dee5fa9ba0eedf36c396 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 29 Jul 2016 15:41:47 +0100 Subject: [PATCH 170/699] Preserve true array type in Java -> GOTO conversion. Fixes #184. Previously all object array allocations became a generic void** when a Java-new operator was lowered into a CPP-new one. Now the type is preserved and is therefore available in the symbol table to build an appropriate source-level type during testcase generation. --- src/goto-programs/builtin_functions.cpp | 37 +++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/src/goto-programs/builtin_functions.cpp b/src/goto-programs/builtin_functions.cpp index d5e27615d3d..63eb18ec549 100644 --- a/src/goto-programs/builtin_functions.cpp +++ b/src/goto-programs/builtin_functions.cpp @@ -830,10 +830,41 @@ void goto_convertt::do_java_new_array( deref, struct_type.components()[2].get_name(), struct_type.components()[2].type()); - side_effect_exprt data_cpp_new_expr(ID_cpp_new_array, data.type()); + + // Allocate a (struct realtype**) instead of a (void**) if possible. + const irept &given_element_type=object_type.find(ID_C_element_type); + typet allocate_data_type; + exprt cast_data_member; + if(given_element_type.is_not_nil()) + { + allocate_data_type= + pointer_typet(static_cast(given_element_type)); + } + else + allocate_data_type=data.type(); + + side_effect_exprt data_cpp_new_expr(ID_cpp_new_array, allocate_data_type); data_cpp_new_expr.set(ID_size, rhs.op0()); + + // Must directly assign the new array to a temporary + // because goto-symex will notice `x=side_effect_exprt` but not + // `x=typecast_exprt(side_effect_exprt(...))` + symbol_exprt new_array_data_symbol= + new_tmp_symbol( + data_cpp_new_expr.type(), + "new_array_data", + dest, + location) + .symbol_expr(); + goto_programt::targett t_p2=dest.add_instruction(ASSIGN); + t_p2->code=code_assignt(new_array_data_symbol, data_cpp_new_expr); + t_p2->source_location=location; + goto_programt::targett t_p=dest.add_instruction(ASSIGN); - t_p->code=code_assignt(data, data_cpp_new_expr); + exprt cast_cpp_new=new_array_data_symbol; + if(cast_cpp_new.type()!=data.type()) + cast_cpp_new=typecast_exprt(cast_cpp_new, data.type()); + t_p->code=code_assignt(data, cast_cpp_new); t_p->source_location=location; // zero-initialize the data @@ -846,7 +877,7 @@ void goto_convertt::do_java_new_array( ns, get_message_handler()); codet array_set(ID_array_set); - array_set.copy_to_operands(data, zero_element); + array_set.copy_to_operands(new_array_data_symbol, zero_element); goto_programt::targett t_d=dest.add_instruction(OTHER); t_d->code=array_set; t_d->source_location=location; From 5851f63744022be7c86f4b9c235182c33d6ffb24 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Mon, 20 Mar 2017 10:09:47 +0000 Subject: [PATCH 171/699] Order string functions in alphabetical order --- .../string_refine_preprocess.cpp | 287 ++++++++++-------- 1 file changed, 163 insertions(+), 124 deletions(-) diff --git a/src/goto-programs/string_refine_preprocess.cpp b/src/goto-programs/string_refine_preprocess.cpp index 8b491bab0ab..f616cd9124f 100644 --- a/src/goto-programs/string_refine_preprocess.cpp +++ b/src/goto-programs/string_refine_preprocess.cpp @@ -1116,14 +1116,54 @@ Function: string_refine_preprocesst::initialize_string_function_table void string_refine_preprocesst::initialize_string_function_table() { + // String library + string_function_calls + ["java::java.lang.String.:(Ljava/lang/String;)V"]= + ID_cprover_string_copy_func; + string_function_calls + ["java::java.lang.String.:(Ljava/lang/StringBuilder;)V"]= + ID_cprover_string_copy_func; + string_function_calls["java::java.lang.String.:([C)V"]= + ID_cprover_string_copy_func; + string_function_calls["java::java.lang.String.:([CII)V"]= + ID_cprover_string_copy_func; + string_function_calls["java::java.lang.String.:()V"]= + ID_cprover_string_empty_string_func; + // Not supported java.lang.String.:(Ljava/lang/StringBuffer;) + + string_functions["java::java.lang.String.charAt:(I)C"]= + ID_cprover_string_char_at_func; string_functions["java::java.lang.String.codePointAt:(I)I"]= ID_cprover_string_code_point_at_func; string_functions["java::java.lang.String.codePointBefore:(I)I"]= ID_cprover_string_code_point_before_func; string_functions["java::java.lang.String.codePointCount:(II)I"]= ID_cprover_string_code_point_count_func; - string_functions["java::java.lang.String.offsetByCodePoints:(II)I"]= - ID_cprover_string_offset_by_code_point_func; + string_functions["java::java.lang.String.compareTo:(Ljava/lang/String;)I"]= + ID_cprover_string_compare_to_func; + // Not supported "java.lang.String.contentEquals" + string_functions + ["java::java.lang.String.concat:(Ljava/lang/String;)Ljava/lang/String;"]= + ID_cprover_string_concat_func; + string_functions + ["java::java.lang.String.contains:(Ljava/lang/CharSequence;)Z"]= + ID_cprover_string_contains_func; + string_functions + ["java::java.lang.String.copyValueOf:([CII)Ljava/lang/String;"]= + ID_cprover_string_copy_func; + string_functions + ["java::java.lang.String.copyValueOf:([C)Ljava/lang/String;"]= + ID_cprover_string_copy_func; + string_functions["java::java.lang.String.endsWith:(Ljava/lang/String;)Z"]= + ID_cprover_string_endswith_func; + string_functions["java::java.lang.String.equals:(Ljava/lang/Object;)Z"]= + ID_cprover_string_equal_func; + string_functions + ["java::java.lang.String.equalsIgnoreCase:(Ljava/lang/String;)Z"]= + ID_cprover_string_equals_ignore_case_func; + // Not supported "java.lang.String.format" + // Not supported "java.lang.String.getBytes" + // Not supported "java.lang.String.getChars" string_functions["java::java.lang.String.hashCode:()I"]= ID_cprover_string_hash_code_func; string_functions["java::java.lang.String.indexOf:(I)I"]= @@ -1134,6 +1174,10 @@ void string_refine_preprocesst::initialize_string_function_table() ID_cprover_string_index_of_func; string_functions["java::java.lang.String.indexOf:(Ljava/lang/String;I)I"]= ID_cprover_string_index_of_func; + string_functions["java::java.lang.String.intern:()Ljava/lang/String;"]= + ID_cprover_string_intern_func; + string_functions["java::java.lang.String.isEmpty:()Z"]= + ID_cprover_string_is_empty_func; string_functions["java::java.lang.String.lastIndexOf:(I)I"]= ID_cprover_string_last_index_of_func; string_functions["java::java.lang.String.lastIndexOf:(II)I"]= @@ -1144,188 +1188,182 @@ void string_refine_preprocesst::initialize_string_function_table() string_functions ["java::java.lang.String.lastIndexOf:(Ljava/lang/String;I)I"]= ID_cprover_string_last_index_of_func; - string_functions - ["java::java.lang.String.concat:(Ljava/lang/String;)Ljava/lang/String;"]= - ID_cprover_string_concat_func; string_functions["java::java.lang.String.length:()I"]= ID_cprover_string_length_func; - string_functions["java::java.lang.StringBuilder.length:()I"]= - ID_cprover_string_length_func; - string_functions["java::java.lang.String.equals:(Ljava/lang/Object;)Z"]= - ID_cprover_string_equal_func; - string_functions - ["java::java.lang.String.equalsIgnoreCase:(Ljava/lang/String;)Z"]= - ID_cprover_string_equals_ignore_case_func; + // Not supported "java.lang.String.matches" + string_functions["java::java.lang.String.offsetByCodePoints:(II)I"]= + ID_cprover_string_offset_by_code_point_func; + // Not supported "java.lang.String.regionMatches" + string_functions["java::java.lang.String.replace:(CC)Ljava/lang/String;"]= + ID_cprover_string_replace_func; + // Not supported "java.lang.String.replace:(LCharSequence;LCharSequence)" + // Not supported "java.lang.String.replaceAll" + // Not supported "java.lang.String.replaceFirst" + // Not supported "java.lang.String.split" string_functions["java::java.lang.String.startsWith:(Ljava/lang/String;)Z"]= ID_cprover_string_startswith_func; string_functions ["java::java.lang.String.startsWith:(Ljava/lang/String;I)Z"]= ID_cprover_string_startswith_func; - string_functions["java::java.lang.String.endsWith:(Ljava/lang/String;)Z"]= - ID_cprover_string_endswith_func; - string_functions["java::java.lang.String.substring:(II)Ljava/lang/String;"]= - ID_cprover_string_substring_func; + string_functions + ["java::java.lang.String.subSequence:(II)Ljava/lang/CharSequence;"]= + ID_cprover_string_substring_func; string_functions["java::java.lang.String.substring:(II)Ljava/lang/String;"]= ID_cprover_string_substring_func; string_functions["java::java.lang.String.substring:(I)Ljava/lang/String;"]= ID_cprover_string_substring_func; - string_functions - ["java::java.lang.StringBuilder.substring:(II)Ljava/lang/String;"]= - ID_cprover_string_substring_func; - string_functions - ["java::java.lang.StringBuilder.substring:(I)Ljava/lang/String;"]= - ID_cprover_string_substring_func; - string_functions - ["java::java.lang.String.subSequence:(II)Ljava/lang/CharSequence;"]= - ID_cprover_string_substring_func; - string_functions["java::java.lang.String.trim:()Ljava/lang/String;"]= - ID_cprover_string_trim_func; + // "java.lang.String.toCharArray has a special treatment in the + // replace_string_calls function string_functions["java::java.lang.String.toLowerCase:()Ljava/lang/String;"]= ID_cprover_string_to_lower_case_func; + // Not supported "java.lang.String.toLowerCase:(Locale)" + // Not supported "java.lang.String.toString:()" string_functions["java::java.lang.String.toUpperCase:()Ljava/lang/String;"]= ID_cprover_string_to_upper_case_func; - string_functions["java::java.lang.String.replace:(CC)Ljava/lang/String;"]= - ID_cprover_string_replace_func; - string_functions - ["java::java.lang.String.contains:(Ljava/lang/CharSequence;)Z"]= - ID_cprover_string_contains_func; - string_functions["java::java.lang.String.compareTo:(Ljava/lang/String;)I"]= - ID_cprover_string_compare_to_func; - string_functions["java::java.lang.String.intern:()Ljava/lang/String;"]= - ID_cprover_string_intern_func; - string_functions["java::java.lang.String.isEmpty:()Z"]= - ID_cprover_string_is_empty_func; - string_functions["java::java.lang.String.charAt:(I)C"]= - ID_cprover_string_char_at_func; - string_functions["java::java.lang.StringBuilder.charAt:(I)C"]= - ID_cprover_string_char_at_func; - string_functions["java::java.lang.CharSequence.charAt:(I)C"]= - ID_cprover_string_char_at_func; - string_functions - ["java::java.lang.StringBuilder.toString:()Ljava/lang/String;"]= + // Not supported "java.lang.String.toUpperCase:(Locale)" + string_functions["java::java.lang.String.trim:()Ljava/lang/String;"]= + ID_cprover_string_trim_func; + string_functions["java::java.lang.String.valueOf:(Z)Ljava/lang/String;"]= + ID_cprover_string_of_bool_func; + string_functions["java::java.lang.String.valueOf:(C)Ljava/lang/String;"]= + ID_cprover_string_of_char_func; + string_functions["java::java.lang.String.valueOf:([C)Ljava/lang/String;"]= ID_cprover_string_copy_func; - + string_functions["java::java.lang.String.valueOf:([CII)Ljava/lang/String;"]= + ID_cprover_string_copy_func; + string_functions["java::java.lang.String.valueOf:(D)Ljava/lang/String;"]= + ID_cprover_string_of_double_func; string_functions["java::java.lang.String.valueOf:(F)Ljava/lang/String;"]= ID_cprover_string_of_float_func; - string_functions["java::java.lang.Float.toString:(F)Ljava/lang/String;"]= - ID_cprover_string_of_float_func; - string_functions["java::java.lang.Integer.toString:(I)Ljava/lang/String;"]= - ID_cprover_string_of_int_func; string_functions["java::java.lang.String.valueOf:(I)Ljava/lang/String;"]= ID_cprover_string_of_int_func; - string_functions["java::java.lang.Integer.toHexString:(I)Ljava/lang/String;"]= - ID_cprover_string_of_int_hex_func; string_functions["java::java.lang.String.valueOf:(L)Ljava/lang/String;"]= ID_cprover_string_of_long_func; - string_functions["java::java.lang.String.valueOf:(D)Ljava/lang/String;"]= - ID_cprover_string_of_double_func; - string_functions["java::java.lang.String.valueOf:(Z)Ljava/lang/String;"]= - ID_cprover_string_of_bool_func; - string_functions["java::java.lang.String.valueOf:(C)Ljava/lang/String;"]= - ID_cprover_string_of_char_func; - string_functions["java::java.lang.Integer.parseInt:(Ljava/lang/String;)I"]= - ID_cprover_string_parse_int_func; + // Not supported "java.lang.String.valueOf:(LObject;)" + + // StringBuilder library + string_function_calls + ["java::java.lang.StringBuilder.:(Ljava/lang/String;)V"]= + ID_cprover_string_copy_func; + string_function_calls["java::java.lang.StringBuilder.:()V"]= + ID_cprover_string_empty_string_func; - side_effect_functions - ["java::java.lang.StringBuilder.append:(Ljava/lang/String;)" - "Ljava/lang/StringBuilder;"]= - ID_cprover_string_concat_func; - side_effect_functions["java::java.lang.StringBuilder.setCharAt:(IC)V"]= - ID_cprover_string_char_set_func; - side_effect_functions - ["java::java.lang.StringBuilder.append:(I)Ljava/lang/StringBuilder;"]= - ID_cprover_string_concat_int_func; - side_effect_functions - ["java::java.lang.StringBuilder.append:(J)Ljava/lang/StringBuilder;"]= - ID_cprover_string_concat_long_func; side_effect_functions ["java::java.lang.StringBuilder.append:(Z)Ljava/lang/StringBuilder;"]= ID_cprover_string_concat_bool_func; side_effect_functions - ["java::java.lang.StringBuilder.append:(C)Ljava/lang/StringBuilder;"]= - ID_cprover_string_concat_char_func; + ["java::java.lang.StringBuilder.append:(C)Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_char_func; + side_effect_functions + ["java::java.lang.StringBuilder.append:([C)" + "Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_func; + // Not supported: "java.lang.StringBuilder.append:([CII)" + // Not supported: "java.lang.StringBuilder.append:(LCharSequence;)" side_effect_functions ["java::java.lang.StringBuilder.append:(D)Ljava/lang/StringBuilder;"]= ID_cprover_string_concat_double_func; side_effect_functions ["java::java.lang.StringBuilder.append:(F)Ljava/lang/StringBuilder;"]= ID_cprover_string_concat_float_func; + side_effect_functions + ["java::java.lang.StringBuilder.append:(I)Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_int_func; + side_effect_functions + ["java::java.lang.StringBuilder.append:(J)Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_long_func; + // Not supported: "java.lang.StringBuilder.append:(LObject;)" + side_effect_functions + ["java::java.lang.StringBuilder.append:(Ljava/lang/String;)" + "Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_func; side_effect_functions ["java::java.lang.StringBuilder.appendCodePoint:(I)" "Ljava/lang/StringBuilder;"]= ID_cprover_string_concat_code_point_func; + // Not supported: "java.lang.StringBuilder.append:(Ljava/lang/StringBuffer;)" + // Not supported: "java.lang.StringBuilder.capacity:()" + string_functions["java::java.lang.StringBuilder.charAt:(I)C"]= + ID_cprover_string_char_at_func; + string_functions["java::java.lang.StringBuilder.codePointAt:(I)I"]= + ID_cprover_string_code_point_at_func; + string_functions["java::java.lang.StringBuilder.codePointBefore:(I)I"]= + ID_cprover_string_code_point_before_func; + string_functions["java::java.lang.StringBuilder.codePointCount:(II)I"]= + ID_cprover_string_code_point_count_func; side_effect_functions ["java::java.lang.StringBuilder.delete:(II)Ljava/lang/StringBuilder;"]= ID_cprover_string_delete_func; side_effect_functions ["java::java.lang.StringBuilder.deleteCharAt:(I)Ljava/lang/StringBuilder;"]= ID_cprover_string_delete_char_at_func; + // Not supported: "java.lang.StringBuilder.ensureCapacity:()" + // Not supported: "java.lang.StringBuilder.getChars:()" + // Not supported: "java.lang.StringBuilder.indexOf:()" side_effect_functions - ["java::java.lang.StringBuilder.insert:(ILjava/lang/String;)" - "Ljava/lang/StringBuilder;"]= + ["java::java.lang.StringBuilder.insert:(IZ)Ljava/lang/StringBuilder;"]= + ID_cprover_string_insert_bool_func; + side_effect_functions + ["java::java.lang.StringBuilder.insert:(IC)Ljava/lang/StringBuilder;"]= + ID_cprover_string_insert_char_func; + side_effect_functions + ["java::java.lang.StringBuilder.insert:(I[C)Ljava/lang/StringBuilder;"]= ID_cprover_string_insert_func; + side_effect_functions + ["java::java.lang.StringBuilder.insert:(I[CII)Ljava/lang/StringBuilder;"]= + ID_cprover_string_insert_func; + // Not supported "java.lang.StringBuilder.insert:(ILCharSequence;)" + // Not supported "java.lang.StringBuilder.insert:(ILCharSequence;II)" + // Not supported "java.lang.StringBuilder.insert:(ID)" + // Not supported "java.lang.StringBuilder.insert:(IF)" side_effect_functions ["java::java.lang.StringBuilder.insert:(II)Ljava/lang/StringBuilder;"]= ID_cprover_string_insert_int_func; side_effect_functions ["java::java.lang.StringBuilder.insert:(IJ)Ljava/lang/StringBuilder;"]= ID_cprover_string_insert_long_func; + // Not supported "java.lang.StringBuilder.insert:(ILObject;)" side_effect_functions - ["java::java.lang.StringBuilder.insert:(IC)Ljava/lang/StringBuilder;"]= - ID_cprover_string_insert_char_func; - side_effect_functions - ["java::java.lang.StringBuilder.insert:(IZ)Ljava/lang/StringBuilder;"]= - ID_cprover_string_insert_bool_func; + ["java::java.lang.StringBuilder.insert:(ILjava/lang/String;)" + "Ljava/lang/StringBuilder;"]= + ID_cprover_string_insert_func; + // Not supported "java.lang.StringBuilder.lastIndexOf" + string_functions["java::java.lang.StringBuilder.length:()I"]= + ID_cprover_string_length_func; + // Not supported "java.lang.StringBuilder.offsetByCodePoints" + // Not supported "java.lang.StringBuilder.replace" + // Not supported "java.lang.StringBuilder.reverse" + side_effect_functions["java::java.lang.StringBuilder.setCharAt:(IC)V"]= + ID_cprover_string_char_set_func; side_effect_functions ["java::java.lang.StringBuilder.setLength:(I)V"]= ID_cprover_string_set_length_func; - - - - side_effect_functions - ["java::java.lang.StringBuilder.append:([C)" - "Ljava/lang/StringBuilder;"]= - ID_cprover_string_concat_func; - side_effect_functions - ["java::java.lang.StringBuilder.insert:(I[CII)Ljava/lang/StringBuilder;"]= - ID_cprover_string_insert_func; - side_effect_functions - ["java::java.lang.StringBuilder.insert:(I[C)Ljava/lang/StringBuilder;"]= - ID_cprover_string_insert_func; - // TODO clean irep ids from insert_char_array etc... - - string_function_calls - ["java::java.lang.String.:(Ljava/lang/String;)V"]= - ID_cprover_string_copy_func; - string_function_calls - ["java::java.lang.String.:(Ljava/lang/StringBuilder;)V"]= - ID_cprover_string_copy_func; - string_function_calls - ["java::java.lang.StringBuilder.:(Ljava/lang/String;)V"]= - ID_cprover_string_copy_func; - string_function_calls["java::java.lang.String.:()V"]= - ID_cprover_string_empty_string_func; - string_function_calls["java::java.lang.StringBuilder.:()V"]= - ID_cprover_string_empty_string_func; - - string_function_calls["java::java.lang.String.:([C)V"]= - ID_cprover_string_copy_func; - string_function_calls["java::java.lang.String.:([CII)V"]= - ID_cprover_string_copy_func; - + // Not supported "java.lang.StringBuilder.subSequence" string_functions - ["java::java.lang.String.valueOf:([CII)Ljava/lang/String;"]= - ID_cprover_string_copy_func; - string_functions - ["java::java.lang.String.valueOf:([C)Ljava/lang/String;"]= - ID_cprover_string_copy_func; + ["java::java.lang.StringBuilder.substring:(II)Ljava/lang/String;"]= + ID_cprover_string_substring_func; string_functions - ["java::java.lang.String.copyValueOf:([CII)Ljava/lang/String;"]= - ID_cprover_string_copy_func; + ["java::java.lang.StringBuilder.substring:(I)Ljava/lang/String;"]= + ID_cprover_string_substring_func; string_functions - ["java::java.lang.String.copyValueOf:([C)Ljava/lang/String;"]= + ["java::java.lang.StringBuilder.toString:()Ljava/lang/String;"]= ID_cprover_string_copy_func; + // Not supported "java.lang.StringBuilder.trimToSize" + // TODO clean irep ids from insert_char_array etc... + + // Other libraries + string_functions["java::java.lang.CharSequence.charAt:(I)C"]= + ID_cprover_string_char_at_func; + string_functions["java::java.lang.Float.toString:(F)Ljava/lang/String;"]= + ID_cprover_string_of_float_func; + string_functions["java::java.lang.Integer.toHexString:(I)Ljava/lang/String;"]= + ID_cprover_string_of_int_hex_func; + string_functions["java::java.lang.Integer.parseInt:(Ljava/lang/String;)I"]= + ID_cprover_string_parse_int_func; + string_functions["java::java.lang.Integer.toString:(I)Ljava/lang/String;"]= + ID_cprover_string_of_int_func; + // C functions c_string_functions["__CPROVER_uninterpreted_string_literal_func"]= ID_cprover_string_literal_func; c_string_functions["__CPROVER_uninterpreted_string_char_at_func"]= @@ -1357,6 +1395,7 @@ void string_refine_preprocesst::initialize_string_function_table() c_string_functions["__CPROVER_uninterpreted_string_of_int_func"]= ID_cprover_string_of_int_func; + // Signatures signatures["java::java.lang.String.equals:(Ljava/lang/Object;)Z"]="SSZ"; signatures["java::java.lang.String.contains:(Ljava/lang/CharSequence;)Z"]= "SSZ"; From 318ab8612592da2211b62a67b97fb8d88b29d74b Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 10 Apr 2017 17:02:51 +0100 Subject: [PATCH 172/699] Improve `class_typet`'s base description This defines an exprt subclass representing a base class instead of using a bare exprt, and enforces proper types when returning the base list. It's the same shape as the existing exprt so old code doesn't need adjusting, it just makes client code neater. --- src/cegis/cegis-util/type_helper.cpp | 6 ++--- src/util/std_types.h | 33 ++++++++++++++++++---------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/cegis/cegis-util/type_helper.cpp b/src/cegis/cegis-util/type_helper.cpp index b20ea9d08e6..e60b597b3a0 100644 --- a/src/cegis/cegis-util/type_helper.cpp +++ b/src/cegis/cegis-util/type_helper.cpp @@ -34,10 +34,10 @@ bool instanceof(const typet &lhs, const typet &rhs, const namespacet &ns) if (type_eq(lhs, rhs, ns)) return true; assert(ID_class == lhs.id()); const class_typet &lhs_class=to_class_type(lhs); - const irept::subt &bases=lhs_class.bases(); - for (const irept &base : bases) + const class_typet::basest &bases=lhs_class.bases(); + for(const exprt &base : bases) { - const typet &type=static_cast(base.find(ID_type)); + const typet &type=base.type(); if (instanceof(ns.follow(type), rhs, ns)) return true; } return false; diff --git a/src/util/std_types.h b/src/util/std_types.h index 02f4a3981a1..4b3ec6e698e 100644 --- a/src/util/std_types.h +++ b/src/util/std_types.h @@ -361,31 +361,40 @@ class class_typet:public struct_typet return is_class()?ID_private:ID_public; } - const irept::subt &bases() const + class baset:public exprt { - return find(ID_bases).get_sub(); + public: + baset():exprt(ID_base) + { + } + + explicit baset(const typet &base):exprt(ID_base, base) + { + } + }; + + typedef std::vector basest; + + const basest &bases() const + { + return (const basest &)find(ID_bases).get_sub(); } - irept::subt &bases() + basest &bases() { - return add(ID_bases).get_sub(); + return (basest &)add(ID_bases).get_sub(); } void add_base(const typet &base) { - bases().push_back(exprt(ID_base, base)); + bases().push_back(baset(base)); } bool has_base(const irep_idt &id) const { - const irept::subt &b=bases(); - - forall_irep(it, b) + for(const auto &b : bases()) { - assert(it->id()==ID_base); - const irept &type=it->find(ID_type); - assert(type.id()==ID_symbol); - if(type.get(ID_identifier)==id) + if(to_symbol_type(b.type()).get(ID_identifier)==id) return true; } From 668f30f0e31a0e2e96745084d52bf670acc02cf7 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 10 Apr 2017 17:04:36 +0100 Subject: [PATCH 173/699] Always convert methods in two phases, even in eager mode Previously in lazy mode we first converted all the method prototypes, then later populated bodies, while in eager mode bodies were populated as we went. Now we always use the former method, so eager mode is like lazy mode except we then populate every method regardless of reachability. This makes the process more uniform, and as a useful side-effect means that the symbol table is populated by the time method conversion happens, so we can check for static initialisers' existence or otherwise. --- .../java_bytecode_convert_class.cpp | 16 +--------------- src/java_bytecode/java_bytecode_language.cpp | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_class.cpp b/src/java_bytecode/java_bytecode_convert_class.cpp index 2926da79fc3..0990027e0a0 100644 --- a/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/src/java_bytecode/java_bytecode_convert_class.cpp @@ -171,21 +171,7 @@ void java_bytecode_convert_classt::convert(const classt &c) method_identifier, method, symbol_table); - if(lazy_methods_mode==LAZY_METHODS_MODE_EAGER) - { - // Upgrade to a fully-realized symbol now: - java_bytecode_convert_method( - *class_symbol, - method, - symbol_table, - get_message_handler(), - max_array_length); - } - else - { - // Wait for our caller to decide what needs elaborating. - lazy_methods[method_identifier]=std::make_pair(class_symbol, &method); - } + lazy_methods[method_identifier]=std::make_pair(class_symbol, &method); } // is this a root class? diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index 43e6fac96c0..444208f0c87 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -542,6 +542,20 @@ bool java_bytecode_languaget::typecheck( if(do_ci_lazy_method_conversion(symbol_table, lazy_methods)) return true; } + else if(lazy_methods_mode==LAZY_METHODS_MODE_EAGER) + { + // Simply elaborate all methods symbols now. + for(const auto &method_sig : lazy_methods) + { + java_bytecode_convert_method( + *method_sig.second.first, + *method_sig.second.second, + symbol_table, + get_message_handler(), + max_user_array_length); + } + } + // Otherwise our caller is in charge of elaborating methods on demand. // now typecheck all if(java_bytecode_typecheck( From 85b1e4f4fa066876a37fa90f271cd37594982b92 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 10 Apr 2017 17:07:10 +0100 Subject: [PATCH 174/699] Invoke static initializers on demand Previously these were run from CPROVER_init; now they are run on demand, using the same rules as the JVM (in brief, when `new` is called, or a static field accessed, or a static method called). This means that a faulting static initializer no longer blocks all coverage, instead blocking only paths that would necessarily call the problematic initializer, and initializers are called in the correct order, which they sometimes depend upon (e.g. a class initializer assuming an enumeration initializer has run before it uses the `.values()` method) For details, see http://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.4 This commit also amends the covered1 test, whose precise results I think are still correct, but are perturbed by this change. --- regression/cbmc-java/covered1/test.desc | 3 +- .../java_bytecode_convert_method.cpp | 206 +++++++++++++++++- .../java_bytecode_convert_method_class.h | 6 + src/java_bytecode/java_entry_point.cpp | 57 ----- 4 files changed, 211 insertions(+), 61 deletions(-) diff --git a/regression/cbmc-java/covered1/test.desc b/regression/cbmc-java/covered1/test.desc index 32af766bdb7..6f78ed37e63 100644 --- a/regression/cbmc-java/covered1/test.desc +++ b/regression/cbmc-java/covered1/test.desc @@ -11,9 +11,8 @@ covered1.class .*\"coveredLines\": \"28\",$ .*\"coveredLines\": \"28\",$ .*\"coveredLines\": \"29\",$ -.*\"coveredLines\": \"9,18\",$ .*\"coveredLines\": \"18\",$ .*\"coveredLines\": \"18\",$ -.*\"coveredLines\": \"18,35\",$ +.*\"coveredLines\": \"35\",$ -- ^warning: ignoring diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 4888810bd83..8d7d63c3c71 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -911,6 +911,174 @@ void java_bytecode_convert_methodt::check_static_field_stub( /*******************************************************************\ +Function: java_bytecode_convert_methodt::class_needs_clinit + + Inputs: classname: Class name + + Outputs: Returns true if the given class or one of its parents + has a static initializer + + Purpose: Determine whether a `new` or static access against `classname` + should be prefixed with a static initialization check. + +\*******************************************************************/ + +bool java_bytecode_convert_methodt::class_needs_clinit( + const irep_idt &classname) +{ + auto findit_any=any_superclass_has_clinit_method.insert({classname, false}); + if(!findit_any.second) + return findit_any.first->second; + + auto findit_here=class_has_clinit_method.insert({classname, false}); + if(findit_here.second) + { + const irep_idt &clinit_name=id2string(classname)+".:()V"; + findit_here.first->second=symbol_table.symbols.count(clinit_name); + } + if(findit_here.first->second) + { + findit_any.first->second=true; + return true; + } + auto findit_symbol=symbol_table.symbols.find(classname); + // Stub class? + if(findit_symbol==symbol_table.symbols.end()) + { + warning() << "SKIPPED: " << classname << eom; + return false; + } + const symbolt &class_symbol=symbol_table.lookup(classname); + for(const auto &base : to_class_type(class_symbol.type).bases()) + { + if(class_needs_clinit(to_symbol_type(base.type()).get_identifier())) + { + findit_any.first->second=true; + return true; + } + } + return false; +} + +/*******************************************************************\ + +Function: java_bytecode_convert_methodt::get_or_create_clinit_wrapper + + Inputs: classname: Class name + + Outputs: Returns a symbol_exprt pointing to the given class' clinit + wrapper if one is required, or nil otherwise. + + Purpose: Create a ::clinit_wrapper the first time a static initializer + might be called. The wrapper method checks whether static init + has already taken place, calls the actual method if + not, and initializes super-classes and interfaces. + +\*******************************************************************/ + +exprt java_bytecode_convert_methodt::get_or_create_clinit_wrapper( + const irep_idt &classname) +{ + if(!class_needs_clinit(classname)) + return static_cast(get_nil_irep()); + + const irep_idt &clinit_wrapper_name= + id2string(classname)+"::clinit_wrapper"; + auto findit=symbol_table.symbols.find(clinit_wrapper_name); + if(findit!=symbol_table.symbols.end()) + return findit->second.symbol_expr(); + + // Create the wrapper now: + const irep_idt &already_run_name= + id2string(classname)+"::clinit_already_run"; + symbolt already_run_symbol; + already_run_symbol.name=already_run_name; + already_run_symbol.pretty_name=already_run_name; + already_run_symbol.base_name="clinit_already_run"; + already_run_symbol.type=bool_typet(); + already_run_symbol.value=false_exprt(); + already_run_symbol.is_lvalue=true; + already_run_symbol.is_state_var=true; + already_run_symbol.is_static_lifetime=true; + already_run_symbol.mode=ID_java; + symbol_table.add(already_run_symbol); + + equal_exprt check_already_run( + already_run_symbol.symbol_expr(), + false_exprt()); + + code_ifthenelset wrapper_body; + wrapper_body.cond()=check_already_run; + code_blockt init_body; + // Note already-run is set *before* calling clinit, in order to prevent + // recursion in clinit methods. + code_assignt set_already_run(already_run_symbol.symbol_expr(), true_exprt()); + init_body.move_to_operands(set_already_run); + const irep_idt &real_clinit_name=id2string(classname)+".:()V"; + const symbolt &class_symbol=symbol_table.lookup(classname); + + auto findsymit=symbol_table.symbols.find(real_clinit_name); + if(findsymit!=symbol_table.symbols.end()) + { + code_function_callt call_real_init; + call_real_init.function()=findsymit->second.symbol_expr(); + init_body.move_to_operands(call_real_init); + } + + for(const auto &base : to_class_type(class_symbol.type).bases()) + { + const auto base_name=to_symbol_type(base.type()).get_identifier(); + exprt base_init_routine=get_or_create_clinit_wrapper(base_name); + if(base_init_routine.is_nil()) + continue; + code_function_callt call_base; + call_base.function()=base_init_routine; + init_body.move_to_operands(call_base); + } + + wrapper_body.then_case()=init_body; + + symbolt wrapper_method_symbol; + code_typet wrapper_method_type; + wrapper_method_type.return_type()=void_typet(); + wrapper_method_symbol.name=clinit_wrapper_name; + wrapper_method_symbol.pretty_name=clinit_wrapper_name; + wrapper_method_symbol.base_name="clinit_wrapper"; + wrapper_method_symbol.type=wrapper_method_type; + wrapper_method_symbol.value=wrapper_body; + wrapper_method_symbol.mode=ID_java; + symbol_table.add(wrapper_method_symbol); + return wrapper_method_symbol.symbol_expr(); +} + +/*******************************************************************\ + +Function: java_bytecode_convert_methodt::get_clinit_call + + Inputs: classname: Class name + + Outputs: Returns a function call to the given class' static initializer + wrapper if one is needed, or a skip instruction otherwise. + + Purpose: Each static access to classname should be prefixed with a check + for necessary static init; this returns a call implementing + that check. + +\*******************************************************************/ + +codet java_bytecode_convert_methodt::get_clinit_call( + const irep_idt &classname) +{ + exprt callee=get_or_create_clinit_wrapper(classname); + if(callee.is_nil()) + return code_skipt(); + code_function_callt ret; + ret.function()=callee; + return ret; +} + +/*******************************************************************\ + Function: java_bytecode_convert_methodt::convert_instructions Inputs: @@ -1378,6 +1546,18 @@ codet java_bytecode_convert_methodt::convert_instructions( call.function().add_source_location()=loc; c=call; + + if(!use_this) + { + codet clinit_call=get_clinit_call(arg0.get(ID_C_class)); + if(clinit_call.get_statement()!=ID_skip) + { + code_blockt ret_block; + ret_block.move_to_operands(clinit_call); + ret_block.move_to_operands(c); + c=std::move(ret_block); + } + } } else if(statement=="return") { @@ -1916,9 +2096,14 @@ codet java_bytecode_convert_methodt::convert_instructions( } results[0]=java_bytecode_promotion(symbol_expr); - // set $assertionDisabled to false - if(field_name.find("$assertionsDisabled")!=std::string::npos) + codet clinit_call=get_clinit_call(arg0.get_string(ID_class)); + if(clinit_call.get_statement()!=ID_skip) + c=clinit_call; + else if(field_name.find("$assertionsDisabled")!=std::string::npos) + { + // set $assertionDisabled to false c=code_assignt(symbol_expr, false_exprt()); + } } else if(statement=="putfield") { @@ -1937,6 +2122,14 @@ codet java_bytecode_convert_methodt::convert_instructions( to_symbol_type(arg0.type()).get_identifier()); } c=code_assignt(symbol_expr, op[0]); + codet clinit_call=get_clinit_call(arg0.get_string(ID_class)); + if(clinit_call.get_statement()!=ID_skip) + { + code_blockt ret_block; + ret_block.move_to_operands(clinit_call); + ret_block.move_to_operands(c); + c=std::move(ret_block); + } } else if(statement==patternt("?2?")) // i2c etc. { @@ -1955,6 +2148,15 @@ codet java_bytecode_convert_methodt::convert_instructions( const exprt tmp=tmp_variable("new", ref_type); c=code_assignt(tmp, java_new_expr); + codet clinit_call= + get_clinit_call(to_symbol_type(arg0.type()).get_identifier()); + if(clinit_call.get_statement()!=ID_skip) + { + code_blockt ret_block; + ret_block.move_to_operands(clinit_call); + ret_block.move_to_operands(c); + c=std::move(ret_block); + } results[0]=tmp; } else if(statement=="newarray" || diff --git a/src/java_bytecode/java_bytecode_convert_method_class.h b/src/java_bytecode/java_bytecode_convert_method_class.h index d260b82bbc8..75cfacd222e 100644 --- a/src/java_bytecode/java_bytecode_convert_method_class.h +++ b/src/java_bytecode/java_bytecode_convert_method_class.h @@ -94,6 +94,8 @@ class java_bytecode_convert_methodt:public messaget expanding_vectort variables; std::set used_local_names; bool method_has_this; + std::map class_has_clinit_method; + std::map any_superclass_has_clinit_method; typedef enum instruction_sizet { @@ -221,6 +223,10 @@ class java_bytecode_convert_methodt:public messaget void check_static_field_stub( const symbol_exprt &se, const irep_idt &basename); + + bool class_needs_clinit(const irep_idt &classname); + exprt get_or_create_clinit_wrapper(const irep_idt &classname); + codet get_clinit_call(const irep_idt &classname); }; #endif diff --git a/src/java_bytecode/java_entry_point.cpp b/src/java_bytecode/java_entry_point.cpp index 3e4de0cdea5..edac8f5cbb3 100644 --- a/src/java_bytecode/java_entry_point.cpp +++ b/src/java_bytecode/java_entry_point.cpp @@ -98,19 +98,6 @@ Function: java_static_lifetime_init \*******************************************************************/ -struct static_initializer_callt -{ - symbol_exprt initializer_symbol; - bool is_enum; -}; - -static bool static_initializer_call_enum_lt( - const static_initializer_callt &a, - const static_initializer_callt &b) -{ - return a.is_enum && !b.is_enum; -} - bool java_static_lifetime_init( symbol_tablet &symbol_table, const source_locationt &source_location, @@ -169,50 +156,6 @@ bool java_static_lifetime_init( } } - // we now need to run all the methods - - std::vector clinits; - - for(symbol_tablet::symbolst::const_iterator - it=symbol_table.symbols.begin(); - it!=symbol_table.symbols.end(); - it++) - { - if(it->second.base_name=="" && - it->second.type.id()==ID_code && - it->second.mode==ID_java) - { - const irep_idt symbol_name= - it->second.symbol_expr().get_identifier(); - const std::string &symbol_str=id2string(symbol_name); - const std::string suffix(".:()V"); - assert(has_suffix(symbol_str, suffix)); - const std::string class_symbol_name= - symbol_str.substr(0, symbol_str.size()-suffix.size()); - const symbolt &class_symbol=symbol_table.lookup(class_symbol_name); - clinits.push_back( - { - it->second.symbol_expr(), - class_symbol.type.get_bool(ID_enumeration) - }); - } - } - - // Call enumeration initialisers before anything else. - // Really we should be calling them the first time they're referenced, - // as acccording to the JVM spec, but this ought to do the trick for - // most cases with much less effort. - std::sort(clinits.begin(), clinits.end(), static_initializer_call_enum_lt); - - for(const auto &clinit : clinits) - { - code_function_callt function_call; - function_call.lhs()=nil_exprt(); - function_call.function()=clinit.initializer_symbol; - function_call.add_source_location()=source_location; - code_block.add(function_call); - } - return false; } From c631419022412f5e6dc210a24037e896bbba14d2 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 10 Apr 2017 17:44:36 +0100 Subject: [PATCH 175/699] Add tests for static initialization order These test mutually dependent static initializers, where the order that fields are referenced in the source program dictate the results of initialization. --- regression/cbmc-java/static_init1/A.class | Bin 0 -> 314 bytes regression/cbmc-java/static_init1/B.class | Bin 0 -> 314 bytes .../cbmc-java/static_init1/static_init.class | Bin 0 -> 588 bytes .../cbmc-java/static_init1/static_init.java | 32 ++++++++++++++++++ regression/cbmc-java/static_init1/test.desc | 8 +++++ regression/cbmc-java/static_init2/A.class | Bin 0 -> 314 bytes regression/cbmc-java/static_init2/B.class | Bin 0 -> 314 bytes .../cbmc-java/static_init2/static_init.class | Bin 0 -> 587 bytes .../cbmc-java/static_init2/static_init.java | 32 ++++++++++++++++++ regression/cbmc-java/static_init2/test.desc | 8 +++++ 10 files changed, 80 insertions(+) create mode 100644 regression/cbmc-java/static_init1/A.class create mode 100644 regression/cbmc-java/static_init1/B.class create mode 100644 regression/cbmc-java/static_init1/static_init.class create mode 100644 regression/cbmc-java/static_init1/static_init.java create mode 100644 regression/cbmc-java/static_init1/test.desc create mode 100644 regression/cbmc-java/static_init2/A.class create mode 100644 regression/cbmc-java/static_init2/B.class create mode 100644 regression/cbmc-java/static_init2/static_init.class create mode 100644 regression/cbmc-java/static_init2/static_init.java create mode 100644 regression/cbmc-java/static_init2/test.desc diff --git a/regression/cbmc-java/static_init1/A.class b/regression/cbmc-java/static_init1/A.class new file mode 100644 index 0000000000000000000000000000000000000000..cc4eabe977212306c26ea2916185d25d0d4bfa6c GIT binary patch literal 314 zcmYL@%}T>i5QWbqY5r}~+NvADr9aSaToyqEK`3=$aVt0RBDcg8YAX6z+J)f42k@c9 zbA#w&?#z61&fNL>{`drNjGY)hx)ECFMc72&R{a2j09yiiW?V8}1pe4mralq4`v*4y z?|gBm1)Yhh^mO%*>*Y-4B}q6g%3o!Cy;v;^ePJxm9&1&b;?~ZFbM>TB#7I&E2m@@V zh!FClQwr^HRI2KJbd}F_Q4^nGk9YaJ*rAXXR*|(d1a=byDZ5=}VQwA1Lta@3Hu(At kOlWBTNsk%^B;Fd%8{9R#e?uECZ5cdtxxGhehrNUB2bL%*e*gdg literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/static_init1/B.class b/regression/cbmc-java/static_init1/B.class new file mode 100644 index 0000000000000000000000000000000000000000..448af9210504502e94f0a39aa6b8e6fe4f08eec5 GIT binary patch literal 314 zcmYL@%Sr=55JhjzWS$w5_=;2!iNBaVtGzBOS&G#EF>CO0p1K_yK-Y z$n8;dQPowq&aJNR#pf4*6Ku!uu^M3w>k+)4v=Lx4KwBX1j4Q@O;P*{o%2R=R*m)4t zE{0E9(7ZNEy_Tvp*`u9x2kK2Fh*1x)l^{Tv zAVSEG&I#IKFIUBL?=~IitfYK~10Lt|Vuv7kR*|(-3hX8b5_Wrhg|Bz?0hzK8tT6kP l*ruWJhaOiNP@ln>!}aE<{Tmu^Y1^T3m)rM=HrYF9EdiV)Dy{$k literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/static_init1/static_init.class b/regression/cbmc-java/static_init1/static_init.class new file mode 100644 index 0000000000000000000000000000000000000000..92cc80f9170adfd67ea86c9d2c4ced1bf3fde393 GIT binary patch literal 588 zcmYk3PjAye5XFD%*xA@|Y0^R)paoh2ZG%KFJywWPKtke=P!STnAjh%LmefJEgW#+5 zLT{Wg5|u!LJ0A)$Yubdv%y?(sym>SJ{pb5nV2fTrlSLn&j?YCd`CR_zmh5v$vmBsV z)LaR;$~Dc3V!j*Yd6E@ol;-zM9`%RGK%w>(^=*@y;*O%WzVTAw?v4hDV)n5~lc(du zev-YgU@06%CRNPr6;b^5N%ZbC-Pn$Yrv$;?Xq?5#Lu28syod@DzqYm82hsZ|Hh0csKFG3BrfB}hqge}CXG7Sh4bS=qNnFS-J7OQi z9*Nx(`zTvXVY@>)fMQ{gOdu|V45>s3-o^V|gb97if}tHe2Ct)%82(~? literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/static_init1/static_init.java b/regression/cbmc-java/static_init1/static_init.java new file mode 100644 index 00000000000..778b6926fcc --- /dev/null +++ b/regression/cbmc-java/static_init1/static_init.java @@ -0,0 +1,32 @@ +public class static_init { + + // A should be initialised first, then B will begin init + // after A.x is set. + public static void main() { + assert(A.x == 1 && B.x == 1 && B.y == 2 && A.y == 2); + } + +} + +class A { + + public static int x; + public static int y; + static { + x = 1; + y = B.y; + } + +} + +class B { + + public static int x; + public static int y; + static { + x = A.x; + y = 2; + + } + +} diff --git a/regression/cbmc-java/static_init1/test.desc b/regression/cbmc-java/static_init1/test.desc new file mode 100644 index 00000000000..30868289dae --- /dev/null +++ b/regression/cbmc-java/static_init1/test.desc @@ -0,0 +1,8 @@ +CORE +static_init.class + +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/cbmc-java/static_init2/A.class b/regression/cbmc-java/static_init2/A.class new file mode 100644 index 0000000000000000000000000000000000000000..cc4eabe977212306c26ea2916185d25d0d4bfa6c GIT binary patch literal 314 zcmYL@%}T>i5QWbqY5r}~+NvADr9aSaToyqEK`3=$aVt0RBDcg8YAX6z+J)f42k@c9 zbA#w&?#z61&fNL>{`drNjGY)hx)ECFMc72&R{a2j09yiiW?V8}1pe4mralq4`v*4y z?|gBm1)Yhh^mO%*>*Y-4B}q6g%3o!Cy;v;^ePJxm9&1&b;?~ZFbM>TB#7I&E2m@@V zh!FClQwr^HRI2KJbd}F_Q4^nGk9YaJ*rAXXR*|(d1a=byDZ5=}VQwA1Lta@3Hu(At kOlWBTNsk%^B;Fd%8{9R#e?uECZ5cdtxxGhehrNUB2bL%*e*gdg literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/static_init2/B.class b/regression/cbmc-java/static_init2/B.class new file mode 100644 index 0000000000000000000000000000000000000000..448af9210504502e94f0a39aa6b8e6fe4f08eec5 GIT binary patch literal 314 zcmYL@%Sr=55JhjzWS$w5_=;2!iNBaVtGzBOS&G#EF>CO0p1K_yK-Y z$n8;dQPowq&aJNR#pf4*6Ku!uu^M3w>k+)4v=Lx4KwBX1j4Q@O;P*{o%2R=R*m)4t zE{0E9(7ZNEy_Tvp*`u9x2kK2Fh*1x)l^{Tv zAVSEG&I#IKFIUBL?=~IitfYK~10Lt|Vuv7kR*|(-3hX8b5_Wrhg|Bz?0hzK8tT6kP l*ruWJhaOiNP@ln>!}aE<{Tmu^Y1^T3m)rM=HrYF9EdiV)Dy{$k literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/static_init2/static_init.class b/regression/cbmc-java/static_init2/static_init.class new file mode 100644 index 0000000000000000000000000000000000000000..6a0da38e0293aaadf5d826f54768613ea7e9b6e6 GIT binary patch literal 587 zcmYk3PjAye5XFD%IN8{7Y1%>)XbXgf(&RudJywWPKtkf5RD?t?$Z=McOX?uoLGV%N zsW;9TiAo^BoezbWwc3Qk%)!tTF(X9Ds zTAJ%VH@KE4?QQL`=IKQW;Z1!F&+`aM8DCVEWiFrOb z9+>o%1xw;Mj1$G&ejY~eo`vtv!}XnLbWY&!k0)tl9>*5m%P)ur)^}Md?E>%{(z3`v>`iI&9)UPw+hPY7T=WDnw(0` zYX1!N)dE=%Un_%3iWjHQmpGDvet~nsMnT0rrB&coPiYoZ<>eLBKGXP#esf0sx8-w6 zKEJH3(UWgnlBkQ*(bTy-W#2A4!os5W9sdOFe!;DL!h_VD#oZ!Bdex>ZO{0}{f BW_ Date: Mon, 27 Mar 2017 14:16:14 +0100 Subject: [PATCH 176/699] Make add_axioms_from_bool add concret constraints Adding universal constraints was not working because the index set wasn't updated for the created constants ("true" and "false"). Adding concrete constraints avoids this problem and is more efficient than updating the index set. For issue diffblue/test-gen#119 --- .../string_constraint_generator_valueof.cpp | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/solvers/refinement/string_constraint_generator_valueof.cpp b/src/solvers/refinement/string_constraint_generator_valueof.cpp index 10fe490259a..a472a73d344 100644 --- a/src/solvers/refinement/string_constraint_generator_valueof.cpp +++ b/src/solvers/refinement/string_constraint_generator_valueof.cpp @@ -228,42 +228,39 @@ string_exprt string_constraint_generatort::add_axioms_from_bool( const exprt &b, const refined_string_typet &ref_type) { string_exprt res=fresh_string(ref_type); - const typet &index_type=ref_type.get_index_type(); + const typet &char_type=ref_type.get_char_type(); assert(b.type()==bool_typet() || b.type().id()==ID_c_bool); typecast_exprt eq(b, bool_typet()); - string_exprt true_string=add_axioms_for_constant("true", ref_type); - string_exprt false_string=add_axioms_for_constant("false", ref_type); - // We add axioms: // a1 : eq => res = |"true"| // a2 : forall i < |"true"|. eq => res[i]="true"[i] // a3 : !eq => res = |"false"| // a4 : forall i < |"false"|. !eq => res[i]="false"[i] - implies_exprt a1(eq, res.axiom_for_has_same_length_as(true_string)); + std::string str_true="true"; + implies_exprt a1(eq, res.axiom_for_has_length(str_true.length())); axioms.push_back(a1); - symbol_exprt qvar=fresh_univ_index("QA_equal_true", index_type); - string_constraintt a2( - qvar, - true_string.length(), - eq, - equal_exprt(res[qvar], true_string[qvar])); - axioms.push_back(a2); - implies_exprt a3( - not_exprt(eq), res.axiom_for_has_same_length_as(false_string)); + for(std::size_t i=0; i Date: Mon, 27 Mar 2017 14:20:18 +0100 Subject: [PATCH 177/699] Adding tests for issue diffblue/test-gen#119 --- .../bug-test-gen-119-2/StringValueOfLong.class | Bin 0 -> 685 bytes .../bug-test-gen-119-2/StringValueOfLong.java | 9 +++++++++ regression/strings/bug-test-gen-119-2/test.desc | 7 +++++++ .../bug-test-gen-119/StringValueOfBool.class | Bin 0 -> 668 bytes .../bug-test-gen-119/StringValueOfBool.java | 10 ++++++++++ regression/strings/bug-test-gen-119/test.desc | 7 +++++++ 6 files changed, 33 insertions(+) create mode 100644 regression/strings/bug-test-gen-119-2/StringValueOfLong.class create mode 100644 regression/strings/bug-test-gen-119-2/StringValueOfLong.java create mode 100644 regression/strings/bug-test-gen-119-2/test.desc create mode 100644 regression/strings/bug-test-gen-119/StringValueOfBool.class create mode 100644 regression/strings/bug-test-gen-119/StringValueOfBool.java create mode 100644 regression/strings/bug-test-gen-119/test.desc diff --git a/regression/strings/bug-test-gen-119-2/StringValueOfLong.class b/regression/strings/bug-test-gen-119-2/StringValueOfLong.class new file mode 100644 index 0000000000000000000000000000000000000000..821230a7f7f90189a889bb177f0407c5ee516cd8 GIT binary patch literal 685 zcmZWnT~8B16g_vl+iACp{h(k`K~T^ZiD<$b#E+mpm;w)NNaStW4$a`QtNX!^=^yY} zO~7cP@BR+|hQ>QvX*JHnojdoQbMBox^ZnQ7uK>2N;ljg$!@kum{eX*WxL)M#MgfcF zuq1HPMF9%}%Pv-MOW-zPc2&l)iV__L@iQIEp05T3IwItEbfA+*gj}$pd#Olb$b6V*@t35|&aaW-y>FxPz9YEL<1z&4LXy-lSb8^B-bvE+7(=T@GQc6}Z$ z-*=#59jU>jT^?1Ea)KvlkU4xmcI+?l-`SOpcfRX#29PP{wo7ohhBh#K2`79~+1ZS)7|J86iVH)+-8*La1og~u1@uBonwSV*~4E+};@=SV| z#taiZJjR-bDR_kZk@REb;R&7+Y6i98%iwt9<*n(xC<-G&=5P~-DZ2j839@xi29te8w0p=Jd$iRIkD1&wCi)M{L+Dnb)*JkyBt!I z@&RYs#VY@f%U?$2nt3hnEO3yR;km@sGOxsIe*FUU)c{fExsWvpMO4Pn_sH=8R;UbWAWA7bhU3Lh>Yei@NmCQ^mX`#e{Ihl4uHRk>3HU87C{v)r5;>u+Xv h0+p(Bj^Yr){sP Date: Mon, 27 Mar 2017 14:27:36 +0100 Subject: [PATCH 178/699] Correct a mistake in the signature for String.valueOf In signature `J` is for long and not `L`. For issur diffblue/test-gen#119 --- src/goto-programs/string_refine_preprocess.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/goto-programs/string_refine_preprocess.cpp b/src/goto-programs/string_refine_preprocess.cpp index f616cd9124f..f6e2b432c92 100644 --- a/src/goto-programs/string_refine_preprocess.cpp +++ b/src/goto-programs/string_refine_preprocess.cpp @@ -1237,7 +1237,7 @@ void string_refine_preprocesst::initialize_string_function_table() ID_cprover_string_of_float_func; string_functions["java::java.lang.String.valueOf:(I)Ljava/lang/String;"]= ID_cprover_string_of_int_func; - string_functions["java::java.lang.String.valueOf:(L)Ljava/lang/String;"]= + string_functions["java::java.lang.String.valueOf:(J)Ljava/lang/String;"]= ID_cprover_string_of_long_func; // Not supported "java.lang.String.valueOf:(LObject;)" From 02f86978dbeaeeccda292403d0ee0ab019b7fe7e Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Wed, 5 Apr 2017 17:38:37 +0100 Subject: [PATCH 179/699] Adding overflow checks in the parsing of integer (#172) This fixes diffblue/test-gen#172. Clarifying number format check and correcting overflow checks. This solves some issues related to the sign characters in string representing numbers. --- .../string_constraint_generator_valueof.cpp | 53 ++++++++++++++----- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/src/solvers/refinement/string_constraint_generator_valueof.cpp b/src/solvers/refinement/string_constraint_generator_valueof.cpp index 10fe490259a..769a356a540 100644 --- a/src/solvers/refinement/string_constraint_generator_valueof.cpp +++ b/src/solvers/refinement/string_constraint_generator_valueof.cpp @@ -642,25 +642,35 @@ exprt string_constraint_generatort::add_axioms_for_correct_number_format( binary_relation_exprt(chr, ID_ge, zero_char), binary_relation_exprt(chr, ID_le, nine_char)); + // TODO: we should have implications in the other direction for correct + // correct => |str| > 0 + exprt non_empty=str.axiom_for_is_longer_than(from_integer(1, index_type)); + axioms.push_back(implies_exprt(correct, non_empty)); + + // correct => (str[0] = '+' or '-' || '0' <= str[0] <= '9') or_exprt correct_first( or_exprt(starts_with_minus, starts_with_plus), starts_with_digit); - exprt has_first=str.axiom_for_is_longer_than(from_integer(1, index_type)); - implies_exprt a1(correct, and_exprt(has_first, correct_first)); - axioms.push_back(a1); + axioms.push_back(implies_exprt(correct, correct_first)); - exprt not_too_long=str.axiom_for_is_shorter_than(max_size); - axioms.push_back(not_too_long); + // correct => str[0]='+' or '-' ==> |str| > 1 + implies_exprt contains_digit( + or_exprt(starts_with_minus, starts_with_plus), + str.axiom_for_is_longer_than(from_integer(2, index_type))); + axioms.push_back(implies_exprt(correct, contains_digit)); - symbol_exprt qvar=fresh_univ_index("number_format", index_type); + // correct => |str| < max_size + axioms.push_back( + implies_exprt(correct, str.axiom_for_is_shorter_than(max_size))); + // forall 1 <= qvar < |str| . correct => '0'<= str[qvar] <= '9' + symbol_exprt qvar=fresh_univ_index("number_format", index_type); and_exprt is_digit( binary_relation_exprt(str[qvar], ID_ge, zero_char), binary_relation_exprt(str[qvar], ID_le, nine_char)); - - string_constraintt a2( + string_constraintt all_digits( qvar, from_integer(1, index_type), str.length(), correct, is_digit); + axioms.push_back(all_digits); - axioms.push_back(a2); return correct; } @@ -706,10 +716,29 @@ exprt string_constraint_generatort::add_axioms_for_parse_int( for(unsigned j=1; j=9) + { + // We have to be careful about overflows + div_exprt div(sum, ten); + equal_exprt no_overflow(div, sum); + axioms.push_back(no_overflow); + } + + sum=plus_exprt_with_overflow_check( + ten_sum, typecast_exprt(minus_exprt(str[j], zero_char), type)); - first_value=mult_exprt(first_value, ten); + + mult_exprt first(first_value, ten); + if(j>=9) + { + // We have to be careful about overflows + div_exprt div_first(first, ten); + implies_exprt no_overflow_first( + starts_with_digit, equal_exprt(div_first, first_value)); + axioms.push_back(no_overflow_first); + } + first_value=first; } // If the length is `size`, we add axioms: From f0004a5d2d825ef486bed8a6e1deb9f1ef3eda3d Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Thu, 6 Apr 2017 09:43:50 +0100 Subject: [PATCH 180/699] Corrections on generated axioms Corrected axiom on positive length not added to axiom list Added missing addition of default axioms in fresh string Removing lemma that makes conditions too strong on strings This was causing the verfication of several goal fail after the first one is concretized. Also added some debugging information. --- .../refinement/string_constraint_generator_main.cpp | 6 ++++-- src/solvers/refinement/string_refinement.cpp | 7 ++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/solvers/refinement/string_constraint_generator_main.cpp b/src/solvers/refinement/string_constraint_generator_main.cpp index c0a6efef0c1..85f79f8bcf6 100644 --- a/src/solvers/refinement/string_constraint_generator_main.cpp +++ b/src/solvers/refinement/string_constraint_generator_main.cpp @@ -177,6 +177,7 @@ string_exprt string_constraint_generatort::fresh_string( symbol_exprt content=fresh_symbol("string_content", type.get_content_type()); string_exprt str(length, content, type); created_strings.insert(str); + add_default_axioms(str); return str; } @@ -246,7 +247,7 @@ string_exprt string_constraint_generatort::convert_java_string_to_string_exprt( /*******************************************************************\ -Function: string_constraint_generatort::add_default_constraints +Function: string_constraint_generatort::add_default_axioms Inputs: s - a string expression @@ -267,7 +268,8 @@ Function: string_constraint_generatort::add_default_constraints void string_constraint_generatort::add_default_axioms( const string_exprt &s) { - s.axiom_for_is_longer_than(from_integer(0, s.length().type())); + axioms.push_back( + s.axiom_for_is_longer_than(from_integer(0, s.length().type()))); if(max_string_length!=std::numeric_limits::max()) axioms.push_back(s.axiom_for_is_shorter_than(max_string_length)); diff --git a/src/solvers/refinement/string_refinement.cpp b/src/solvers/refinement/string_refinement.cpp index 0ea7966ef61..bc5b2816522 100644 --- a/src/solvers/refinement/string_refinement.cpp +++ b/src/solvers/refinement/string_refinement.cpp @@ -332,7 +332,6 @@ void string_refinementt::concretize_string(const exprt &expr) { string_exprt str=to_string_expr(expr); exprt length=get(str.length()); - add_lemma(equal_exprt(str.length(), length)); exprt content=str.content(); replace_expr(symbol_resolve, content); found_length[content]=length; @@ -350,6 +349,7 @@ void string_refinementt::concretize_string(const exprt &expr) else { size_t concretize_limit=found_length.to_long(); + assert(concretize_limit<=generator.max_string_length); concretize_limit=concretize_limit>generator.max_string_length? generator.max_string_length:concretize_limit; exprt content_expr=str.content(); @@ -596,7 +596,11 @@ decision_proceduret::resultt string_refinementt::dec_solve() do_concretizing=false; } else + { + debug() << "check_SAT: the model is correct and " + << "does not need concretizing" << eom; return D_SATISFIABLE; + } } display_index_set(); @@ -611,6 +615,7 @@ decision_proceduret::resultt string_refinementt::dec_solve() } break; default: + debug() << "check_SAT: default return " << res << eom; return res; } } From 94e9c647e222ce30f614253a4001e80102023491 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Fri, 7 Apr 2017 09:41:43 +0100 Subject: [PATCH 181/699] Various improvements in string refinement Update documentation of the string refinement Correct bounds in substitute_array_lists adding debugging information Fixing the manual setting of type in if expressions When converting array accesses to if expressions, the check made on the type for the case of unknown value was not done correctly and could cause an assertion violation or a mismatch in types. --- src/solvers/refinement/string_refinement.cpp | 55 ++++++++++++++------ 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/src/solvers/refinement/string_refinement.cpp b/src/solvers/refinement/string_refinement.cpp index bc5b2816522..6cd090d4b1d 100644 --- a/src/solvers/refinement/string_refinement.cpp +++ b/src/solvers/refinement/string_refinement.cpp @@ -26,13 +26,12 @@ Author: Alberto Griggio, alberto.griggio@gmail.com Constructor: string_refinementt - Inputs: a namespace, a decision procedure, a bound on the number - of refinements and a boolean flag `concretize_result` + Inputs: + _ns - a namespace + _prop - a decision procedure + refinement_bound - a bound on the number of refinements Purpose: refinement_bound is a bound on the number of refinement allowed. - if `concretize_result` is set to true, at the end of the decision - procedure, the solver try to find a concrete value for each - character \*******************************************************************/ @@ -167,15 +166,17 @@ void string_refinementt::add_instantiations() Function: string_refinementt::add_symbol_to_symbol_map() - Inputs: a symbol and the expression to map it to + Inputs: + lhs - a symbol expression + rhs - an expression to map it to Purpose: keeps a map of symbols to expressions, such as none of the mapped values exist as a key \*******************************************************************/ -void string_refinementt::add_symbol_to_symbol_map -(const exprt &lhs, const exprt &rhs) +void string_refinementt::add_symbol_to_symbol_map( + const exprt &lhs, const exprt &rhs) { assert(lhs.id()==ID_symbol); @@ -259,6 +260,21 @@ exprt string_refinementt::substitute_function_applications(exprt expr) return expr; } +/*******************************************************************\ + +Function: string_refinementt::is_char_array + + Inputs: + type - a type + + Outputs: true if the given type is an array of java characters + + Purpose: distinguish char array from other types + + TODO: this is only for java char array and does not work for other languages + +\*******************************************************************/ + bool string_refinementt::is_char_array(const typet &type) const { if(type.id()==ID_symbol) @@ -269,9 +285,11 @@ bool string_refinementt::is_char_array(const typet &type) const /*******************************************************************\ -Function: string_refinementt::boolbv_set_equality_to_true +Function: string_refinementt::add_axioms_for_string_assigns - Inputs: the lhs and rhs of an equality expression + Inputs: + lhs - left hand side of an equality expression + rhs - right and side of the equality Outputs: false if the lemmas were added successfully, true otherwise @@ -279,8 +297,8 @@ Function: string_refinementt::boolbv_set_equality_to_true \*******************************************************************/ -bool string_refinementt::add_axioms_for_string_assigns(const exprt &lhs, - const exprt &rhs) +bool string_refinementt::add_axioms_for_string_assigns( + const exprt &lhs, const exprt &rhs) { if(is_char_array(rhs.type())) { @@ -443,6 +461,8 @@ void string_refinementt::set_to(const exprt &expr, bool value) { debug() << "(sr::set_to) WARNING: ignoring " << from_expr(expr) << " [inconsistent types]" << eom; + debug() << "lhs has type: " << eq_expr.lhs().type().pretty(12) << eom; + debug() << "rhs has type: " << eq_expr.rhs().type().pretty(12) << eom; return; } @@ -1037,16 +1057,17 @@ void string_refinementt::substitute_array_access(exprt &expr) const } auto op_it=++array_expr.operands().rbegin(); + for(size_t i=last_index-1; op_it!=array_expr.operands().rend(); ++op_it, --i) { equal_exprt equals(index_expr.index(), from_integer(i, java_int_type())); - ite=if_exprt(equals, *op_it, ite); - if(ite.type()!=char_type) + if(op_it->type()!=char_type) { - assert(ite.id()==ID_unknown); - ite.type()=char_type; + assert(op_it->id()==ID_unknown); + op_it->type()=char_type; } + ite=if_exprt(equals, *op_it, ite); } expr=ite; } @@ -1752,7 +1773,7 @@ exprt string_refinementt::substitute_array_lists(exprt expr) const expr.operands()[0], expr.operands()[1]); - for(size_t i=2; i Date: Wed, 12 Apr 2017 11:04:58 +0100 Subject: [PATCH 182/699] Assign variables for all parameters The pointer code is well suited to handle all types, not just pointers, with just a minor tweak for booleans. --- src/java_bytecode/java_object_factory.cpp | 71 +++++++++++------------ 1 file changed, 33 insertions(+), 38 deletions(-) diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index f806a6427cb..55dfc96931f 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -464,11 +464,20 @@ void java_object_factoryt::gen_nondet_init( } else { - side_effect_expr_nondett se=side_effect_expr_nondett(type); + code_assignt assign; + assign.lhs()=expr; + assign.add_source_location()=loc; - code_assignt code(expr, se); - code.add_source_location()=loc; - init_code.copy_to_operands(code); + if(type.id()==ID_c_bool) + { + assign.rhs()=get_nondet_bool(type); + } + else + { + assign.rhs()=side_effect_expr_nondett(type); + } + + init_code.copy_to_operands(assign); } } @@ -702,43 +711,29 @@ exprt object_factory( const source_locationt &loc, message_handlert &message_handler) { - if(type.id()==ID_pointer) - { - symbolt &aux_symbol=new_tmp_symbol( - symbol_table, - loc, - type); - aux_symbol.is_static_lifetime=true; + symbolt &aux_symbol=new_tmp_symbol(symbol_table, loc, type); + aux_symbol.is_static_lifetime=true; - exprt object=aux_symbol.symbol_expr(); + exprt object=aux_symbol.symbol_expr(); - java_object_factoryt state( - init_code, - !allow_null, - max_nondet_array_length, - symbol_table, - message_handler, - loc); - state.gen_nondet_init( - object, - false, - "", - false, - false, - false, - typet(), - NO_UPDATE_IN_PLACE); + java_object_factoryt state( + init_code, + !allow_null, + max_nondet_array_length, + symbol_table, + message_handler, + loc); + state.gen_nondet_init( + object, + false, + "", + false, + false, + false, + typet(), + NO_UPDATE_IN_PLACE); - return object; - } - else if(type.id()==ID_c_bool) - { - // We force this to 0 and 1 and won't consider - // other values. - return get_nondet_bool(type); - } - else - return side_effect_expr_nondett(type); + return object; } /*******************************************************************\ From 7755820ab7a99f8dcb3d93ca025109fcdc695777 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Tue, 11 Apr 2017 22:28:14 +0200 Subject: [PATCH 183/699] Fix boolean to string conversion in expr2java Fixes diffblue/test-gen#206. --- src/java_bytecode/expr2java.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/java_bytecode/expr2java.cpp b/src/java_bytecode/expr2java.cpp index 3cd487e234a..aac8b17d335 100644 --- a/src/java_bytecode/expr2java.cpp +++ b/src/java_bytecode/expr2java.cpp @@ -195,9 +195,15 @@ std::string expr2javat::convert_constant( const constant_exprt &src, unsigned &precedence) { - if(src.type().id()==ID_bool) + if(src.type().id()==ID_c_bool) + { + if(!src.is_zero()) + return "true"; + else + return "false"; + } + else if(src.type().id()==ID_bool) { - // Java has built-in Boolean constants, in contrast to C if(src.is_true()) return "true"; else if(src.is_false()) @@ -482,7 +488,6 @@ std::string expr2javat::convert( const exprt &src, unsigned &precedence) { - const typet &type=ns.follow(src.type()); if(src.id()=="java-this") return convert_java_this(src, precedence=15); if(src.id()==ID_java_instanceof) @@ -510,13 +515,8 @@ std::string expr2javat::convert( } else if(src.id()==ID_java_string_literal) return '"'+MetaString(src.get_string(ID_value))+'"'; - else if(src.id()==ID_constant && (type.id()==ID_bool || type.id()==ID_c_bool)) - { - if(src.is_true()) - return "true"; - else - return "false"; - } + else if(src.id()==ID_constant) + return convert_constant(to_constant_expr(src), precedence=16); else return expr2ct::convert(src, precedence); } From 396a53091a7af2b3da4c23130daaa08ef24a47ba Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Wed, 12 Apr 2017 09:18:37 +0200 Subject: [PATCH 184/699] Remove unused nullptr case in expr2java Was supposedly copy and paste from expr2cpp --- src/java_bytecode/expr2java.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/java_bytecode/expr2java.cpp b/src/java_bytecode/expr2java.cpp index aac8b17d335..5f07b5850fb 100644 --- a/src/java_bytecode/expr2java.cpp +++ b/src/java_bytecode/expr2java.cpp @@ -499,8 +499,6 @@ std::string expr2javat::convert( else if(src.id()==ID_side_effect && src.get(ID_statement)==ID_throw) return convert_function(src, "throw", precedence=16); - else if(src.is_constant() && to_constant_expr(src).get_value()==ID_nullptr) - return "nullptr"; else if(src.id()==ID_unassigned) return "?"; else if(src.id()=="pod_constructor") From 718683f6f8ac55905f8eeb6ad57de07165e330d7 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 12 Apr 2017 12:43:13 +0100 Subject: [PATCH 185/699] Remove trace_stackt This is only used in derivative out-of-repo classes, and therefore should be moved there. --- src/goto-programs/interpreter_class.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/goto-programs/interpreter_class.h b/src/goto-programs/interpreter_class.h index 8ea3ad620b2..d1051eeb93f 100644 --- a/src/goto-programs/interpreter_class.h +++ b/src/goto-programs/interpreter_class.h @@ -90,16 +90,6 @@ class interpretert:public messaget const dynamic_typest &get_dynamic_types() { return dynamic_types; } protected: - struct trace_stack_entryt - { - irep_idt func_name; - mp_integer this_address; - irep_idt capture_symbol; - bool is_super_call; - std::vector param_values; - }; - typedef std::vector trace_stackt; - const symbol_tablet &symbol_table; // This is a cache so that we don't have to create it when a call needs it From 5c289b18c7bf80d562ee60c91c0de6b5d42614c0 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 12 Apr 2017 14:33:08 +0100 Subject: [PATCH 186/699] Support ID_C_bool in exprt::is_zero --- src/util/expr.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/util/expr.cpp b/src/util/expr.cpp index 963def60b12..3b480e4bfe2 100644 --- a/src/util/expr.cpp +++ b/src/util/expr.cpp @@ -449,7 +449,9 @@ bool exprt::is_zero() const assert(false); return rat_value.is_zero(); } - else if(type_id==ID_unsignedbv || type_id==ID_signedbv) + else if(type_id==ID_unsignedbv || + type_id==ID_signedbv || + type_id==ID_c_bool) { return constant.value_is_zero_string(); } From 083d8a65f9a7305d8cd55a979b84c50c9df3ab70 Mon Sep 17 00:00:00 2001 From: Cristina Date: Wed, 12 Apr 2017 12:36:37 +0100 Subject: [PATCH 187/699] Always report exceptinal output in __CPROVER_start --- src/goto-programs/remove_exceptions.cpp | 47 +++++++++++++++++++++---- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/src/goto-programs/remove_exceptions.cpp b/src/goto-programs/remove_exceptions.cpp index e73eba8d2ec..5058164147c 100644 --- a/src/goto-programs/remove_exceptions.cpp +++ b/src/goto-programs/remove_exceptions.cpp @@ -192,6 +192,39 @@ void remove_exceptionst::instrument_exception_handler( /*******************************************************************\ +Function: get_exceptional_output + +Inputs: + +Outputs: + +Purpose: finds the instruction where the exceptional output is set + or the end of the function if no such output exists + +\*******************************************************************/ + +static goto_programt::targett get_exceptional_output( + goto_programt &goto_program) +{ + Forall_goto_program_instructions(it, goto_program) + { + const irep_idt &statement=it->code.get_statement(); + if(statement==ID_output) + { + assert(it->code.operands().size()>=2); + const exprt &expr=it->code.op1(); + assert(expr.id()==ID_symbol); + const symbol_exprt &symbol=to_symbol_expr(expr); + if(id2string(symbol.get_identifier()).find(EXC_SUFFIX) + !=std::string::npos) + return it; + } + } + return goto_program.get_end_function(); +} + +/*******************************************************************\ + Function: remove_exceptionst::instrument_throw Inputs: @@ -217,13 +250,14 @@ void remove_exceptionst::instrument_throw( assert(instr_it->code.operands().size()==1); // find the end of the function - goto_programt::targett end_function=goto_program.get_end_function(); - if(end_function!=instr_it) + goto_programt::targett exceptional_output= + get_exceptional_output(goto_program); + if(exceptional_output!=instr_it) { // jump to the end of the function // this will appear after the GOTO-based dynamic dispatch below goto_programt::targett t_end=goto_program.insert_after(instr_it); - t_end->make_goto(end_function); + t_end->make_goto(exceptional_output); t_end->source_location=instr_it->source_location; t_end->function=instr_it->function; } @@ -322,13 +356,14 @@ void remove_exceptionst::instrument_function_call( symbol_exprt callee_exc=callee_exc_symbol.symbol_expr(); // find the end of the function - goto_programt::targett end_function=goto_program.get_end_function(); - if(end_function!=instr_it) + goto_programt::targett exceptional_output= + get_exceptional_output(goto_program); + if(exceptional_output!=instr_it) { // jump to the end of the function // this will appear after the GOTO-based dynamic dispatch below goto_programt::targett t_end=goto_program.insert_after(instr_it); - t_end->make_goto(end_function); + t_end->make_goto(exceptional_output); t_end->source_location=instr_it->source_location; t_end->function=instr_it->function; } From a1b6ea374f6e720ec446755fd1d7fb32efb9096a Mon Sep 17 00:00:00 2001 From: Vojtech Forejt Date: Wed, 12 Apr 2017 14:49:26 +0100 Subject: [PATCH 188/699] Travis fix: ccache limit was in the wrong section --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a2396927dab..7cebb781ff4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,10 +37,10 @@ matrix: before_install: - HOMEBREW_NO_AUTO_UPDATE=1 brew install ccache - export PATH=/usr/local/opt/ccache/libexec:$PATH + - ccache -M 1G env: - COMPILER="ccache clang++ -Qunused-arguments -fcolor-diagnostics" - CCACHE_CPP2=yes - - ccache -M 1G # Ubuntu Linux with glibc using g++-5 - os: linux From 035ae9211b85cecdf074e3851aec1a3c27187894 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 12 Apr 2017 18:29:30 +0100 Subject: [PATCH 189/699] Restore array-set for nondet arrays This was removed because the array is certain to be overwritten with nondets, and thus the zero-init was worthless-- however, for the special case of a zero-length array the init statement was the only assignment, making the difference between the interpreter assigning it value {} and assigning it no value at all. Ideally we should omit this most of the time, but its cost is probably minimal and it's much simpler to keep it than to track down all the special cases required to deal with a symbol that is referred to but never defined in the inputs map. --- src/java_bytecode/java_object_factory.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index 55dfc96931f..3846845a336 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -549,7 +549,10 @@ void java_object_factoryt::gen_nondet_array_init( side_effect_exprt java_new_array(ID_java_new_array, expr.type()); java_new_array.copy_to_operands(length_sym_expr); - java_new_array.set(ID_skip_initialize, true); + // Retain the array_set instruction for the special case of a + // zero-length array, where this will be the only assignment against + // the array's identifier. + java_new_array.set(ID_skip_initialize, false); java_new_array.type().subtype().set(ID_C_element_type, element_type); codet assign=code_assignt(expr, java_new_array); assign.add_source_location()=loc; @@ -798,4 +801,3 @@ void gen_nondet_init( typet(), update_in_place); } - From 3c5ae1a56823f65414c099c4651508431117aa4b Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 12 Apr 2017 19:18:11 +0100 Subject: [PATCH 190/699] Allow checkcast of null pointer This used to assume checkcast required a non-null ref, but actually checkcast (null) always passes. This may increase coverage but is quite low priority. --- .../java_bytecode_convert_method.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 8d7d63c3c71..cf96e356136 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -1368,10 +1368,20 @@ codet java_bytecode_convert_methodt::convert_instructions( // TODO: convert assertions to exceptions. assert(op.size()==1 && results.size()==1); binary_predicate_exprt check(op[0], ID_java_instanceof, arg0); - c=code_assertt(check); - c.add_source_location().set_comment("Dynamic cast check"); - c.add_source_location().set_property_class("bad-dynamic-cast"); - + code_assertt assert_class(check); + assert_class.add_source_location().set_comment("Dynamic cast check"); + assert_class.add_source_location().set_property_class("bad-dynamic-cast"); + // checkcast passes when the operand is null. + empty_typet voidt; + pointer_typet voidptr(voidt); + exprt null_check_op=op[0]; + if(null_check_op.type()!=voidptr) + null_check_op.make_typecast(voidptr); + code_ifthenelset conditional_check; + notequal_exprt op_not_null(null_check_op, null_pointer_exprt(voidptr)); + conditional_check.cond()=std::move(op_not_null); + conditional_check.then_case()=std::move(assert_class); + c=std::move(conditional_check); results[0]=op[0]; } else if(statement=="invokedynamic") From 77ac3a243d6ba86496664a0e76b93a8b09d1db85 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 13 Apr 2017 11:14:55 +0100 Subject: [PATCH 191/699] Fix Java object factory recursion set Previously it was vulnerable to indirect recursion (i.e. A has a B*, B has an A*); this removes that possibility and also simplifies use of the recursion set to only consider pointer edges rather than directly nested struct types, which can't be used to construct an infinite object graph by themselves. This should address some of the cases of prematurely truncated object graphs the incorrect recursion test was trying to solve. --- src/java_bytecode/java_object_factory.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index 3846845a336..823c900f504 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -316,9 +316,8 @@ void java_object_factoryt::gen_nondet_init( { const struct_typet &struct_type=to_struct_type(subtype); const irep_idt struct_tag=struct_type.get_tag(); - // set to null if found in recursion set and not a sub-type - if(recursion_set.find(struct_tag)!=recursion_set.end() && - struct_tag==class_identifier) + // If this is a recursive type of some kind, set null. + if(!recursion_set.insert(struct_tag).second) { if(update_in_place==NO_UPDATE_IN_PLACE) set_null(expr, pointer_type); @@ -403,9 +402,6 @@ void java_object_factoryt::gen_nondet_init( if(!is_sub) class_identifier=struct_tag; - recursion_set.insert(struct_tag); - assert(!recursion_set.empty()); - for(const auto &component : components) { const typet &component_type=component.type(); @@ -460,7 +456,6 @@ void java_object_factoryt::gen_nondet_init( substruct_in_place); } } - recursion_set.erase(struct_tag); } else { From 241dbee1659d343d6104442695783d0567bbe0d4 Mon Sep 17 00:00:00 2001 From: reuk Date: Tue, 14 Mar 2017 16:33:45 +0000 Subject: [PATCH 192/699] Add org.cprover package and makefile --- src/java_bytecode/library/Makefile | 26 ++++ .../library/src/org/cprover/CProver.java | 121 +++++++++++++++++- 2 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 src/java_bytecode/library/Makefile diff --git a/src/java_bytecode/library/Makefile b/src/java_bytecode/library/Makefile new file mode 100644 index 00000000000..aa51ec1694a --- /dev/null +++ b/src/java_bytecode/library/Makefile @@ -0,0 +1,26 @@ +all: org.cprover.jar + +SOURCE_DIR := src +BINARY_DIR := classes + +FIND := find + +JAVAC := javac +JFLAGS := -sourcepath $(SOURCE_DIR) -d $(BINARY_DIR) + +CLASSPATH := SOURCE_DIR + +all_javas := $(shell $(FIND) $(SOURCE_DIR) -name '*.java') + +$(BINARY_DIR): + mkdir -p $(BINARY_DIR) + +.PHONY: compile +compile: $(BINARY_DIR) + $(JAVAC) $(JFLAGS) $(all_javas) + +JAR := jar +JARFLAGS := -cf + +org.cprover.jar: compile + $(JAR) $(JARFLAGS) $@ -C $(BINARY_DIR) org diff --git a/src/java_bytecode/library/src/org/cprover/CProver.java b/src/java_bytecode/library/src/org/cprover/CProver.java index 72c3eeb1d70..0dcae58c67e 100644 --- a/src/java_bytecode/library/src/org/cprover/CProver.java +++ b/src/java_bytecode/library/src/org/cprover/CProver.java @@ -3,9 +3,124 @@ public final class CProver { public static boolean enableAssume=true; - public static void assume(boolean condition) + public static boolean enableNondet=true; + + public static boolean nondetBoolean() + { + if (enableNondet) + { + throw new RuntimeException( + "Cannot execute program with CProver.nondetBoolean()"); + } + + return false; + } + + public static byte nondetByte() + { + if (enableNondet) + { + throw new RuntimeException( + "Cannot execute program with CProver.nondetByte()"); + } + + return 0; + } + + public static char nondetChar() + { + if (enableNondet) + { + throw new RuntimeException( + "Cannot execute program with CProver.nondetChar()"); + } + + return '\0'; + } + + public static short nondetShort() + { + if (enableNondet) + { + throw new RuntimeException( + "Cannot execute program with CProver.nondetShort()"); + } + + return 0; + } + + public static int nondetInt() + { + if (enableNondet) + { + throw new RuntimeException( + "Cannot execute program with CProver.nondetInt()"); + } + + return 0; + } + + public static long nondetLong() + { + if (enableNondet) + { + throw new RuntimeException( + "Cannot execute program with CProver.nondetLong()"); + } + + return 0; + } + + public static float nondetFloat() + { + if (enableNondet) + { + throw new RuntimeException( + "Cannot execute program with CProver.nondetFloat()"); + } + + return 0; + } + + public static double nondetDouble() + { + if (enableNondet) + { + throw new RuntimeException( + "Cannot execute program with CProver.nondetDouble()"); + } + + return 0; + } + + public static T nondetWithNull() + { + if (enableNondet) + { + throw new RuntimeException( + "Cannot execute program with CProver.nondetWithNull(T)"); + } + + return null; + } + + public static T nondetWithoutNull() + { + if (enableNondet) + { + throw new RuntimeException( + "Cannot execute program with CProver.nondetWithoutNull(T)"); + } + + return null; + } + + public static void assume(boolean condition) { if(enableAssume) - throw new RuntimeException("Cannot execute program with CProver.assume()"); - } + { + throw new RuntimeException( + "Cannot execute program with CProver.assume()"); + } + } } From 7ed66a1a0632d278706056a9395947478a9a43ef Mon Sep 17 00:00:00 2001 From: reuk Date: Tue, 14 Mar 2017 16:58:20 +0000 Subject: [PATCH 193/699] Add tests --- regression/cbmc-java/Makefile | 13 ++++++++ .../cbmc-java/NondetArray/NondetArray.class | Bin 0 -> 722 bytes .../cbmc-java/NondetArray/NondetArray.java | 10 ++++++ regression/cbmc-java/NondetArray/test.desc | 6 ++++ .../cbmc-java/NondetArray2/NondetArray2.class | Bin 0 -> 907 bytes .../cbmc-java/NondetArray2/NondetArray2.java | 15 +++++++++ regression/cbmc-java/NondetArray2/test.desc | 6 ++++ .../cbmc-java/NondetArray3/NondetArray3.class | Bin 0 -> 935 bytes .../cbmc-java/NondetArray3/NondetArray3.java | 16 ++++++++++ regression/cbmc-java/NondetArray3/test.desc | 6 ++++ .../cbmc-java/NondetArray4/NondetArray4.class | Bin 0 -> 806 bytes .../cbmc-java/NondetArray4/NondetArray4.java | 14 ++++++++ regression/cbmc-java/NondetArray4/test.desc | 6 ++++ .../NondetAssume1/NondetAssume1.class | Bin 0 -> 722 bytes .../NondetAssume1/NondetAssume1.java | 11 +++++++ regression/cbmc-java/NondetAssume1/test.desc | 6 ++++ regression/cbmc-java/NondetAssume2/A.class | Bin 0 -> 256 bytes regression/cbmc-java/NondetAssume2/B.class | Bin 0 -> 258 bytes regression/cbmc-java/NondetAssume2/C.class | Bin 0 -> 258 bytes .../NondetAssume2/NondetAssume2.class | Bin 0 -> 759 bytes .../NondetAssume2/NondetAssume2.java | 17 ++++++++++ regression/cbmc-java/NondetAssume2/test.desc | 6 ++++ .../NondetBoolean/NondetBoolean.class | Bin 0 -> 659 bytes .../NondetBoolean/NondetBoolean.java | 10 ++++++ regression/cbmc-java/NondetBoolean/test.desc | 6 ++++ .../cbmc-java/NondetByte/NondetByte.class | Bin 0 -> 657 bytes .../cbmc-java/NondetByte/NondetByte.java | 10 ++++++ regression/cbmc-java/NondetByte/test.desc | 6 ++++ .../NondetCastToObject.class | Bin 0 -> 779 bytes .../NondetCastToObject.java | 11 +++++++ .../cbmc-java/NondetCastToObject/test.desc | 6 ++++ .../cbmc-java/NondetChar/NondetChar.class | Bin 0 -> 657 bytes .../cbmc-java/NondetChar/NondetChar.java | 10 ++++++ regression/cbmc-java/NondetChar/test.desc | 6 ++++ .../cbmc-java/NondetDirectFromMethod/A.class | Bin 0 -> 265 bytes .../NondetDirectFromMethod.class | Bin 0 -> 808 bytes .../NondetDirectFromMethod.java | 19 +++++++++++ .../NondetDirectFromMethod/test.desc | 6 ++++ .../cbmc-java/NondetDouble/NondetDouble.class | Bin 0 -> 667 bytes .../cbmc-java/NondetDouble/NondetDouble.java | 10 ++++++ regression/cbmc-java/NondetDouble/test.desc | 6 ++++ .../cbmc-java/NondetFloat/NondetFloat.class | Bin 0 -> 663 bytes .../cbmc-java/NondetFloat/NondetFloat.java | 10 ++++++ regression/cbmc-java/NondetFloat/test.desc | 6 ++++ .../cbmc-java/NondetGenericArray/A.class | Bin 0 -> 287 bytes .../cbmc-java/NondetGenericArray/B.class | Bin 0 -> 263 bytes .../cbmc-java/NondetGenericArray/C.class | Bin 0 -> 263 bytes .../NondetGenericArray.class | Bin 0 -> 953 bytes .../NondetGenericArray.java | 30 ++++++++++++++++++ .../cbmc-java/NondetGenericArray/test.desc | 6 ++++ .../cbmc-java/NondetGenericRecursive/A.class | Bin 0 -> 249 bytes .../cbmc-java/NondetGenericRecursive/B.class | Bin 0 -> 267 bytes .../cbmc-java/NondetGenericRecursive/C.class | Bin 0 -> 267 bytes .../NondetGenericRecursive.class | Bin 0 -> 731 bytes .../NondetGenericRecursive.java | 24 ++++++++++++++ .../NondetGenericRecursive/test.desc | 6 ++++ .../cbmc-java/NondetGenericRecursive2/A.class | Bin 0 -> 250 bytes .../cbmc-java/NondetGenericRecursive2/B.class | Bin 0 -> 268 bytes .../cbmc-java/NondetGenericRecursive2/C.class | Bin 0 -> 268 bytes .../NondetGenericRecursive2.class | Bin 0 -> 879 bytes .../NondetGenericRecursive2.java | 27 ++++++++++++++++ .../NondetGenericRecursive2/test.desc | 6 ++++ .../cbmc-java/NondetGenericWithNull/B.class | Bin 0 -> 264 bytes .../NondetGenericWithNull.class | Bin 0 -> 772 bytes .../NondetGenericWithNull.java | 13 ++++++++ .../cbmc-java/NondetGenericWithNull/test.desc | 6 ++++ .../NondetGenericWithoutNull/B.class | Bin 0 -> 267 bytes .../NondetGenericWithoutNull.class | Bin 0 -> 740 bytes .../NondetGenericWithoutNull.java | 12 +++++++ .../NondetGenericWithoutNull/test.desc | 6 ++++ .../cbmc-java/NondetInt/NondetInt.class | Bin 0 -> 653 bytes regression/cbmc-java/NondetInt/NondetInt.java | 10 ++++++ regression/cbmc-java/NondetInt/test.desc | 6 ++++ .../cbmc-java/NondetLong/NondetLong.class | Bin 0 -> 659 bytes .../cbmc-java/NondetLong/NondetLong.java | 10 ++++++ regression/cbmc-java/NondetLong/test.desc | 6 ++++ .../cbmc-java/NondetShort/NondetShort.class | Bin 0 -> 661 bytes .../cbmc-java/NondetShort/NondetShort.java | 10 ++++++ regression/cbmc-java/NondetShort/test.desc | 6 ++++ 79 files changed, 438 insertions(+) create mode 100644 regression/cbmc-java/NondetArray/NondetArray.class create mode 100644 regression/cbmc-java/NondetArray/NondetArray.java create mode 100644 regression/cbmc-java/NondetArray/test.desc create mode 100644 regression/cbmc-java/NondetArray2/NondetArray2.class create mode 100644 regression/cbmc-java/NondetArray2/NondetArray2.java create mode 100644 regression/cbmc-java/NondetArray2/test.desc create mode 100644 regression/cbmc-java/NondetArray3/NondetArray3.class create mode 100644 regression/cbmc-java/NondetArray3/NondetArray3.java create mode 100644 regression/cbmc-java/NondetArray3/test.desc create mode 100644 regression/cbmc-java/NondetArray4/NondetArray4.class create mode 100644 regression/cbmc-java/NondetArray4/NondetArray4.java create mode 100644 regression/cbmc-java/NondetArray4/test.desc create mode 100644 regression/cbmc-java/NondetAssume1/NondetAssume1.class create mode 100644 regression/cbmc-java/NondetAssume1/NondetAssume1.java create mode 100644 regression/cbmc-java/NondetAssume1/test.desc create mode 100644 regression/cbmc-java/NondetAssume2/A.class create mode 100644 regression/cbmc-java/NondetAssume2/B.class create mode 100644 regression/cbmc-java/NondetAssume2/C.class create mode 100644 regression/cbmc-java/NondetAssume2/NondetAssume2.class create mode 100644 regression/cbmc-java/NondetAssume2/NondetAssume2.java create mode 100644 regression/cbmc-java/NondetAssume2/test.desc create mode 100644 regression/cbmc-java/NondetBoolean/NondetBoolean.class create mode 100644 regression/cbmc-java/NondetBoolean/NondetBoolean.java create mode 100644 regression/cbmc-java/NondetBoolean/test.desc create mode 100644 regression/cbmc-java/NondetByte/NondetByte.class create mode 100644 regression/cbmc-java/NondetByte/NondetByte.java create mode 100644 regression/cbmc-java/NondetByte/test.desc create mode 100644 regression/cbmc-java/NondetCastToObject/NondetCastToObject.class create mode 100644 regression/cbmc-java/NondetCastToObject/NondetCastToObject.java create mode 100644 regression/cbmc-java/NondetCastToObject/test.desc create mode 100644 regression/cbmc-java/NondetChar/NondetChar.class create mode 100644 regression/cbmc-java/NondetChar/NondetChar.java create mode 100644 regression/cbmc-java/NondetChar/test.desc create mode 100644 regression/cbmc-java/NondetDirectFromMethod/A.class create mode 100644 regression/cbmc-java/NondetDirectFromMethod/NondetDirectFromMethod.class create mode 100644 regression/cbmc-java/NondetDirectFromMethod/NondetDirectFromMethod.java create mode 100644 regression/cbmc-java/NondetDirectFromMethod/test.desc create mode 100644 regression/cbmc-java/NondetDouble/NondetDouble.class create mode 100644 regression/cbmc-java/NondetDouble/NondetDouble.java create mode 100644 regression/cbmc-java/NondetDouble/test.desc create mode 100644 regression/cbmc-java/NondetFloat/NondetFloat.class create mode 100644 regression/cbmc-java/NondetFloat/NondetFloat.java create mode 100644 regression/cbmc-java/NondetFloat/test.desc create mode 100644 regression/cbmc-java/NondetGenericArray/A.class create mode 100644 regression/cbmc-java/NondetGenericArray/B.class create mode 100644 regression/cbmc-java/NondetGenericArray/C.class create mode 100644 regression/cbmc-java/NondetGenericArray/NondetGenericArray.class create mode 100644 regression/cbmc-java/NondetGenericArray/NondetGenericArray.java create mode 100644 regression/cbmc-java/NondetGenericArray/test.desc create mode 100644 regression/cbmc-java/NondetGenericRecursive/A.class create mode 100644 regression/cbmc-java/NondetGenericRecursive/B.class create mode 100644 regression/cbmc-java/NondetGenericRecursive/C.class create mode 100644 regression/cbmc-java/NondetGenericRecursive/NondetGenericRecursive.class create mode 100644 regression/cbmc-java/NondetGenericRecursive/NondetGenericRecursive.java create mode 100644 regression/cbmc-java/NondetGenericRecursive/test.desc create mode 100644 regression/cbmc-java/NondetGenericRecursive2/A.class create mode 100644 regression/cbmc-java/NondetGenericRecursive2/B.class create mode 100644 regression/cbmc-java/NondetGenericRecursive2/C.class create mode 100644 regression/cbmc-java/NondetGenericRecursive2/NondetGenericRecursive2.class create mode 100644 regression/cbmc-java/NondetGenericRecursive2/NondetGenericRecursive2.java create mode 100644 regression/cbmc-java/NondetGenericRecursive2/test.desc create mode 100644 regression/cbmc-java/NondetGenericWithNull/B.class create mode 100644 regression/cbmc-java/NondetGenericWithNull/NondetGenericWithNull.class create mode 100644 regression/cbmc-java/NondetGenericWithNull/NondetGenericWithNull.java create mode 100644 regression/cbmc-java/NondetGenericWithNull/test.desc create mode 100644 regression/cbmc-java/NondetGenericWithoutNull/B.class create mode 100644 regression/cbmc-java/NondetGenericWithoutNull/NondetGenericWithoutNull.class create mode 100644 regression/cbmc-java/NondetGenericWithoutNull/NondetGenericWithoutNull.java create mode 100644 regression/cbmc-java/NondetGenericWithoutNull/test.desc create mode 100644 regression/cbmc-java/NondetInt/NondetInt.class create mode 100644 regression/cbmc-java/NondetInt/NondetInt.java create mode 100644 regression/cbmc-java/NondetInt/test.desc create mode 100644 regression/cbmc-java/NondetLong/NondetLong.class create mode 100644 regression/cbmc-java/NondetLong/NondetLong.java create mode 100644 regression/cbmc-java/NondetLong/test.desc create mode 100644 regression/cbmc-java/NondetShort/NondetShort.class create mode 100644 regression/cbmc-java/NondetShort/NondetShort.java create mode 100644 regression/cbmc-java/NondetShort/test.desc diff --git a/regression/cbmc-java/Makefile b/regression/cbmc-java/Makefile index a1b44c5a948..dcdf752aea1 100644 --- a/regression/cbmc-java/Makefile +++ b/regression/cbmc-java/Makefile @@ -23,3 +23,16 @@ clean: find -name '*.out' -execdir $(RM) '{}' \; find -name '*.gb' -execdir $(RM) '{}' \; $(RM) tests.log + +%.class: %.java ../../src/org.cprover.jar + javac -g -cp ../../src/org.cprover.jar:. $< + +nondet_java_files := $(shell find . -name "Nondet*.java") +nondet_class_files := $(patsubst %.java, %.class, $(nondet_java_files)) + +.PHONY: nondet-class-files +nondet-class-files: $(nondet_class_files) + +.PHONY: clean-nondet-class-files +clean-nondet-class-files: + -rm $(nondet_class_files) diff --git a/regression/cbmc-java/NondetArray/NondetArray.class b/regression/cbmc-java/NondetArray/NondetArray.class new file mode 100644 index 0000000000000000000000000000000000000000..57858ac292f69439cc0e65d1d6c7b77fb150b7f8 GIT binary patch literal 722 zcmZvZ&2G~`6ot>kPR4bd=BI5)!ao#9K*F2us1Q|vl?g~iMU>UV9<>u(yBgb-c$K~Y zYe1q1q?R2L&x8=yPDm=j!k&9)?)~mLGe3WSJq56VfsG~fY+S@8j%DPArsZ$k4$zzp>aVP@@w#!i2RFO&_G8p~A4ud(21IbYLR3t~)!C2~- zc`-xFi+vI92(9vbwrQsODq*O3qc{p=x}~*v_kbV=LPbQ3#}gX;#+!&E;f5mGbDxhV z(odu!QYIpdeSQ(m8VeFMk_v0)bWnsv$+8_MS zQGLN2hIHEu?La0<%V4gFJf|5Q&{gl!({Oq_fHgX~3yKW-$Q&4!DROCLw3hFlfPJ8# zggX5z#ioG<#m=+3+xxVoVqMrm`~g&v;fT({|xIG+@V>r_$1z43MJ8OX78Ol_v4&1^YhQQBLH)lvtVJ&!WCTQ$XU3C@f4D{ z&T+$ni7}1|3zL}Qm}cl7cUmo>0_l6L$Fk*Yx}wg&HWB-yDDqz8%zqhHNqPRI0vL7s0Yp&b#sh>e6(iNBt#Du53HI zPRVt=th!>0TN(K!-4632)64A-23rtVzNrp_PXImTMN7Af2 zZb+2qN=Sp=PST1?*T^tf7cHqo{Tw-|6ohm@1sfQnS76Z-Vd-4Nl{}3WNdf9bUWqIt zYfK-4eIh4;H2uvus3AkXeVTwi^wSO)I4?e?Y)+A-uSooWR?!w`s>P#uU7I(uMpplb zp<>o3-!}_+^8k8d@x8(JPkw!dv4`Hm2XuXh`T7w2IGU@)b4TKSoc<~LEQ}K939?0k z{D|g8c&4FKJc%p@2`5c&BjdP-A>;^c3U`smFrm9d=Xq!+lwxueI5ZY5V*DG!8ESI* moXlKI6Ug)>50Kge*Y}}oUts*JO4QXr!d{BB8=*}CqkjQF8L<8U literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetArray2/NondetArray2.java b/regression/cbmc-java/NondetArray2/NondetArray2.java new file mode 100644 index 00000000000..2f9bcedd797 --- /dev/null +++ b/regression/cbmc-java/NondetArray2/NondetArray2.java @@ -0,0 +1,15 @@ +import org.cprover.CProver; + +class NondetArray2 +{ + void main() + { + Integer[] ints = CProver.nondetWithoutNull(); + + int num = 0; + for (Integer i : ints) { + num *= i.intValue(); + } + assert num == 0; + } +} diff --git a/regression/cbmc-java/NondetArray2/test.desc b/regression/cbmc-java/NondetArray2/test.desc new file mode 100644 index 00000000000..5e84e0dbf7c --- /dev/null +++ b/regression/cbmc-java/NondetArray2/test.desc @@ -0,0 +1,6 @@ +CORE +NondetArray2.class +--function NondetArray2.main --unwind 5 +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/cbmc-java/NondetArray3/NondetArray3.class b/regression/cbmc-java/NondetArray3/NondetArray3.class new file mode 100644 index 0000000000000000000000000000000000000000..e07d736d747d1f5db68cd8c7326775ef18db25e5 GIT binary patch literal 935 zcmZuv%T5$Q6g@TFJvB59!vF)rLqSC4A&fkNQ9&iB32_`B7>u}TW;)Q=bd#EH68HXu zEZwkH6EK>fI}?AwAMg`g81VEkG9tn=sLD;v5Dfat%n~ zyu_dhBQ9RRMTtu$hA=EKBG5KyS1OJQ-N3KhaVz$!=adD+ia>JK_1*BMfHpL|ETAt0 zWk(=gaDAs3ZLT`%Y1}N(S_n$Ew`?mn-q(tHxb9X2nhV9iFFWD9QueE<8${W(U7z?a zZ!T=u+jicw{k8m}A3AG}iW^)%tUZ&fd(B!Sdy$*WN| zmx4%@oO^CeFmsy2czmgaCNxWoTDXic3yrV@a&IGsF%zxIWPk#| zTO?x_rSwq71UX$}yhSFDDI;b%0-f~~vgjata;ou_xQ|ZcsG$c}iO@~XJv{G&{u^Bq z+7UsM61_}Cyy(U+bY}>4=0xap)dC>Xn%YCd4y3*dUHbt2U&mr>0}1PP?CV)>66pH_ DFp{_m literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetArray3/NondetArray3.java b/regression/cbmc-java/NondetArray3/NondetArray3.java new file mode 100644 index 00000000000..c061aa693f2 --- /dev/null +++ b/regression/cbmc-java/NondetArray3/NondetArray3.java @@ -0,0 +1,16 @@ +import org.cprover.CProver; + +class NondetArray3 +{ + void main() + { + Integer[] ints = CProver.nondetWithoutNull(); + assert ints != null; + + int num = 0; + for (Integer i : ints) { + num *= i.intValue(); + } + assert num == 0; + } +} diff --git a/regression/cbmc-java/NondetArray3/test.desc b/regression/cbmc-java/NondetArray3/test.desc new file mode 100644 index 00000000000..a0f68ce5a41 --- /dev/null +++ b/regression/cbmc-java/NondetArray3/test.desc @@ -0,0 +1,6 @@ +CORE +NondetArray3.class +--function NondetArray3.main --unwind 5 +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/cbmc-java/NondetArray4/NondetArray4.class b/regression/cbmc-java/NondetArray4/NondetArray4.class new file mode 100644 index 0000000000000000000000000000000000000000..dbe5532ccfb0e88fb8371545e5b337bd776ef8f7 GIT binary patch literal 806 zcmZWmO-~b16g_V~I;9NsgNiLG2%@&AbkmhqBB`2?)MA3ch^y)Jr3?-;z zt2x}nEep2==2o33k}CGXAbRXYPS2Np0kJ2LX?cMcZwTnM`mTV{4*OCd-|+(39Uk_i zdXY2>lscj7_`8nslKZ%5#QR<(Fx%;dL0`t3N;z+v56E)pcmeqx#ulT;a9Q?(nC<1) zodf6CY4}bsXlwty+lm$;=J{Q%!Z8_ z3pE>ctl7w6TA(tSvU%qIiBh2wurCr=xMSlk?gd zenP)*e1vg=Le=<%>2EM!og(uiVb)XT1#*L;G-P2=T85%#Ib)fu$+YH(aXd|xI?%6|()mLUF;#pB U82{T&=uBw#qvUa}@uFezA4iRp3IG5A literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetArray4/NondetArray4.java b/regression/cbmc-java/NondetArray4/NondetArray4.java new file mode 100644 index 00000000000..4b4e15aaad7 --- /dev/null +++ b/regression/cbmc-java/NondetArray4/NondetArray4.java @@ -0,0 +1,14 @@ +import org.cprover.CProver; + +class NondetArray4 +{ + void main() + { + int a = 1; + int b = 2; + int c = 3; + + Integer[] ints = CProver.nondetWithoutNull(); + assert ints != null; + } +} diff --git a/regression/cbmc-java/NondetArray4/test.desc b/regression/cbmc-java/NondetArray4/test.desc new file mode 100644 index 00000000000..fd419bab2d4 --- /dev/null +++ b/regression/cbmc-java/NondetArray4/test.desc @@ -0,0 +1,6 @@ +CORE +NondetArray4.class +--function NondetArray4.main +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/cbmc-java/NondetAssume1/NondetAssume1.class b/regression/cbmc-java/NondetAssume1/NondetAssume1.class new file mode 100644 index 0000000000000000000000000000000000000000..bcdca197547fabfd5126639491b8e34bc80dbaba GIT binary patch literal 722 zcmZWnO>fgc5PchO;@EXan$i#&J_@9e7KDY=8xblBAXO@*Qc)#x+t{nJ#j&fkQ}J7R zfg5K)q7{|Oo!^8IvyPRj;;^%`J2UUio88}kf1U$a$0HXGmRxjj!_dPs7&x4COhPH|Nk%;$w;+<-Hsdb`> z?h=fRRS#=;$k4bbc{4hYK}Lf~^u8Y)>f}gjf3TD93{ITu*^DWJ=0XZ8G(XZt%6daH zr}_odAfgyUE0n3yGMqI-nzIQ72w;e1dK!lwjWyb)eex_?Bn=E#$n$Auw3pXTz`l}G zLY-_SzqHUG-=Ypgf)KP&>|f$TpTq?65wB$>Sa<*rC2pd{?#|54 ze%_zw3%~?j3mRG`+9o;#x^b)s#!Q7OofEYFU{BB&(LoYgt_tNkyLd9*2`^x!>qfo^ z_99j}|BHHhQVEZ`&Xiznqb&C2QWf@f6dq*iBuRFW!~?8UnAu$OUU~Qc-5HcnFTI#2G0!u735j!G5V%4x9_S2d$Qf<;7?`0*i@Bki4+@XuP^PMyI zo;&Z)^95jnu8lGr3vCM>0trIdTTBV&Ohqc2v+NHJ1Y;E+CBgAjBsclhm&soEAv;|! z4n%kmiPE|-jqI#aowVd6dl%tAG$p@$Ox40oT3;?EETsSd literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetAssume2/C.class b/regression/cbmc-java/NondetAssume2/C.class new file mode 100644 index 0000000000000000000000000000000000000000..bbf6b9b7eaefdf0ebb7df435b7e489815784f53e GIT binary patch literal 258 zcmXX=%MQU%5IsY+)Y}(WVxfuH5eZGK8WzOoBZm_WH0=Xm7W&| zB0PvhY5o_D?5t9qDSXi`h9XCweOzct-1>7=m+d>|T zChk~R#)^qmf%>u=MN-Eq45BA0a)-Vg35bC}ep3Z1ek71>wRZ)KZa9(xm7WS@e=;6Q z{W2*QsP#h6^>xw@++LT7@=ok}Z=Sn{ zX(tH_6gEA7Hrv_>C)$(GR66Mb*!qEc&ct0CEwl;SwXuedjS_5uW>Vq!Zm{Q& zz*OW@twYVJ7obesvvD8m0@d@D7sCVT#oSP+_Z;s~heuL7-R;y0%mt~iS1R7`PkdjX z(Q5bpZKk|D*GuUX-Wnupten?$eZC1SjAW#=9Gy|*LgEP@xc32;csYw_71d@Uie8o< zMT1!M99lt}TRVYxPbY&a|M@go#5{d_T7VkrjDW^j^IKMDm{~nV<~#4v`2o{-2P1n5 z;{$TXsC0g!^ac6XCosPy=-Cv#27`VXCXwo-vBGRJX<>>so5Wk<5_1BV`Bp;qH!3EY oTcSZtSI$Umr1XIKTHzCl$1?^Wk^5gwf|EnW-byrIWst$Ozfjqa#Q*>R literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetAssume2/NondetAssume2.java b/regression/cbmc-java/NondetAssume2/NondetAssume2.java new file mode 100644 index 00000000000..1f8f74a3464 --- /dev/null +++ b/regression/cbmc-java/NondetAssume2/NondetAssume2.java @@ -0,0 +1,17 @@ +import org.cprover.CProver; + +class A { int x; } + +class B { A a; } + +class C { B b; } + +class NondetAssume2 +{ + void main() + { + C c = CProver.nondetWithNull(); + CProver.assume(c != null); + assert c != null; + } +} diff --git a/regression/cbmc-java/NondetAssume2/test.desc b/regression/cbmc-java/NondetAssume2/test.desc new file mode 100644 index 00000000000..19abaa63e8a --- /dev/null +++ b/regression/cbmc-java/NondetAssume2/test.desc @@ -0,0 +1,6 @@ +CORE +NondetAssume2.class +--function NondetAssume2.main +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/cbmc-java/NondetBoolean/NondetBoolean.class b/regression/cbmc-java/NondetBoolean/NondetBoolean.class new file mode 100644 index 0000000000000000000000000000000000000000..0b4ed3f79156e27d3d0dfb59472e18e7af84d0cb GIT binary patch literal 659 zcmZWn%TC)s6g?9=u`z~(P(sS9yaip<8+IT>N!t|#BpwpoP3#d27!MjdsJ{X~z#5PM zQK{_vO$c$v3ZV#D<9lc3+;i@^_P?k5zW^36>%m3c!$%Btp@d-vBOYwj9gKPy!zTyh z4E@tQO@+>+O44sK<;_?`4D1&}X-OtBTV}B4=64zFhKdA3c}*r_y>;9adfR{*s%t9b z@h;cW?AwQSb|6!OUROyZvQ?#G!IMRzIp#7Uf!_>0TNw|Je)5xcjk^@aZAouSwR9+c z$XwtJ$CpEX%6)XhcQD~&5>r09;4#$AMG*63Klu7$>ATiSlhPXo2h%=gFvU=LE!k)u ziZG*jD7_zqCt95f9W*xcNCe6MHu90sgvzhwjhM#BP>Vz=wTL+K$YgqN*V$Q=n7RFG+eFqOb*qC$h(8D5@ z96TaSt%y9Ax=>k~zg4;DCNd__KB2auQdPVnSgX%>33fY+B_ZgjRBrW-yHbBPU_zsl zMIzZ1TA6eI(k>2FPVhThSsKe?^J^j3nd4Zfl-bYNHVOB(3lV+!AWr&4?nadKdwSbh zPe<~-G97{u$;%^gDtwH?cktN9GFE(y!6URxB1}Yj5WX2K^iJzc6TDHmgC{2-Dnuat`poJDl8o-y{s8CUWQwT_{ipXtaui7n+U9IgtOkaRA zAkhjWxPinoA;hc`l0!Inc6N8>`=lhH76%VvvnTLLKO0 zhI&8td3eZ`)cfh7l^)B4q0t}2Q6SPDPtt?<)#ya{>0`nga~Tm!th-P68TUdS9eK0+ zrTvuq?_ToL94*&b+V#V!9%nz!lrLUL&Az%w@JJ)NaIs|Lu8VuP@1l*43kMa3)|~I@ zKj+VtiWO;D#ImvNqKgL%wRzt}C(SNaN1lJG;xnPV-s^m2xDw@--^lcMkcA-)q22kP z$s!Ft8Zzl$rFAYmf%Y zJX#s8h3yNl50n_FQY_|&CTf(slL9QGPCH;_)|^tcK_{D+F#6peu&wv7%uARbVV$Ge z{fWv~6y9E-_+3MrIdmNsPFw4!keFx)+D_!?~tT>lG)G@1VZ literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetCastToObject/NondetCastToObject.java b/regression/cbmc-java/NondetCastToObject/NondetCastToObject.java new file mode 100644 index 00000000000..133df3f9f4e --- /dev/null +++ b/regression/cbmc-java/NondetCastToObject/NondetCastToObject.java @@ -0,0 +1,11 @@ +import org.cprover.CProver; + +class NondetCastToObject +{ + void main() + { + Object o = CProver.nondetWithNull(); + CProver.assume(o != null); + assert o != null; + } +} diff --git a/regression/cbmc-java/NondetCastToObject/test.desc b/regression/cbmc-java/NondetCastToObject/test.desc new file mode 100644 index 00000000000..5d3b98bb583 --- /dev/null +++ b/regression/cbmc-java/NondetCastToObject/test.desc @@ -0,0 +1,6 @@ +CORE +NondetCastToObject.class +--function NondetCastToObject.main +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/cbmc-java/NondetChar/NondetChar.class b/regression/cbmc-java/NondetChar/NondetChar.class new file mode 100644 index 0000000000000000000000000000000000000000..4d05d0b75dd80a169aae2e690cb7c767f0671844 GIT binary patch literal 657 zcmZWnT~E|d5IwW)ZcC|jS#((t1r+)4!M^YYA)2aBE0~}p@OHPofs3Ujw_U|L}*#UB}MatmO#X&_c#Zmvp|dKwsj92Pe}IcN&oQL6F~iS&#yw!;rnhKQg&EGbSv3Hr fTa6!ZuHe{TU|Zi|{XeUrsH5h;G#kzGp@z;sAX0gW literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetChar/NondetChar.java b/regression/cbmc-java/NondetChar/NondetChar.java new file mode 100644 index 00000000000..f9570d8a5d2 --- /dev/null +++ b/regression/cbmc-java/NondetChar/NondetChar.java @@ -0,0 +1,10 @@ +import org.cprover.CProver; + +class NondetChar +{ + static void main() + { + char x = CProver.nondetChar(); + assert x == '\0'; + } +} diff --git a/regression/cbmc-java/NondetChar/test.desc b/regression/cbmc-java/NondetChar/test.desc new file mode 100644 index 00000000000..96ecd2f6735 --- /dev/null +++ b/regression/cbmc-java/NondetChar/test.desc @@ -0,0 +1,6 @@ +CORE +NondetChar.class +--function NondetChar.main +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/cbmc-java/NondetDirectFromMethod/A.class b/regression/cbmc-java/NondetDirectFromMethod/A.class new file mode 100644 index 0000000000000000000000000000000000000000..6d3758b230af9b1e55332b653b5f147e7ef1bce6 GIT binary patch literal 265 zcmXX=yKcfj5S+y?;+XJgX;K0OZqfxsLLj6_4iq5zvwaGOj8D28`L9%wQse{pD8wF6 z?C#9$?BjI)`v>rXUJMWI2%QLB0tt?HLO4;ivTp=$Fx(RSnJy)vovB(bkB3~EjmRrj zdYLXnwG~D=eiwbaQ(ruqOrmK9OBe)|TV5P|{JTh{N IT36T81-_0i*#H0l literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetDirectFromMethod/NondetDirectFromMethod.class b/regression/cbmc-java/NondetDirectFromMethod/NondetDirectFromMethod.class new file mode 100644 index 0000000000000000000000000000000000000000..6dafdc80b07ffff6f12571880630e21e02bc602f GIT binary patch literal 808 zcmZuuO>fgc5Ph3C+0=Dunl>R2K1y342?z_RH!4Jw(o+%;MMdHP*9Jg!~ z(coCKv5pOn+YHMaB95g_R20VBDi*^)`V4HJp}3_&l{{w1H(PrQRyXn`!(vZ`a*&RP zQol6K43%EwiC|A?W$u%rl^m#;q23!rp)ZqdrKOkb=xE%R$wA~lVknQZ?1fBH9jb8D zVJI|Py$=1d#zKV*3%iN%-t@)MgtN5e1rtg3Zj@?I?kFRmaq$}u4#lx>uz*V(cO2YB zlYDg?%)@c8f-0#q9d01Pk=yw@gr{0ZnxS?vCr8Uc8}~^54Et<&Nakpiksi6;k&cd~ zcDv8B$gmV<6L_V_cbW{+AYfP_qyOT`_u{P94QMSS!^&tpl<6#H#S)e%cm6b>f@QkF%!Mij{E(sn^H0cq zNB$k9=i$ydIG@66)3^K7ZQ!*Juuf2EpQ7*s^IuSWeFpx`h{+weCdq}ffC>n3Q|!Ky>0AO+2VSuwNvp=5d8z3 z0jaG(f;+znA!e;Kjl^MgX6NyJ^Z5Pu`%eJtSPK!L7veIm%%P5}KCXrE(DQLU#0@O_ zxJg)85k(0meo8$eFG_P$kp)=Hp z$hL)1_CIlYS5evA;d5bJe`v+Z@bC#wg j>lHoF?$nRrAHnxN!*jpE{l8laQG*jbwliJgkAv<%3fFzr literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetDouble/NondetDouble.java b/regression/cbmc-java/NondetDouble/NondetDouble.java new file mode 100644 index 00000000000..451fcf4db7e --- /dev/null +++ b/regression/cbmc-java/NondetDouble/NondetDouble.java @@ -0,0 +1,10 @@ +import org.cprover.CProver; + +class NondetDouble +{ + static void main() + { + double x = CProver.nondetDouble(); + assert x == 0; + } +} diff --git a/regression/cbmc-java/NondetDouble/test.desc b/regression/cbmc-java/NondetDouble/test.desc new file mode 100644 index 00000000000..631edbe5024 --- /dev/null +++ b/regression/cbmc-java/NondetDouble/test.desc @@ -0,0 +1,6 @@ +CORE +NondetDouble.class +--function NondetDouble.main +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/cbmc-java/NondetFloat/NondetFloat.class b/regression/cbmc-java/NondetFloat/NondetFloat.class new file mode 100644 index 0000000000000000000000000000000000000000..9b26f72c773ab21696c86a2784ef8a1711bd2201 GIT binary patch literal 663 zcmZWnO;6iE5PfSqv2k4TL4gF?LMd%2hx)>;sG>^ADbPw(Ah>Pp6|NeV(3t$CHK0LI1%wTp5Wjt~5)Q5wXi)TLO zFz@0y!^9%bGNE&+((I$mcrOt#1KVRLugX;B?-}f+H`@$OTg8H*+Lfu;>>u`o{$h$5 z8eJ9fWSeVg&Vx%Q|0*+vN8L@8#v<<|is$c$%>WRuYppfykwl4s;g%U59M6j&IiZ@IX%QKi_FQUPkHllRaVf_JFe z?z7f(4Fpj${H7&!R%Q;vT@GPOO2# z>zUcv*}eb&{s9=E?W2sqL(@ZxK!Q+?CPRWdQd$*broH}_;LP%!Bm|Mta(ViRrP+u$ zW2GJCiO9CXD9hiXQykRMCQUiXU*{*2$hori&NA0KSuCWMMkNzt#N|5`XHka>kM~ar zP0Pbf=zX|~Q<)U#qQpl6#Lq$Hjd*~SDzlJ(+pB!tKvxDO)VR7&u?nAY{bj%hBOBCs Gx;`J~t}e*{ literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetGenericArray/C.class b/regression/cbmc-java/NondetGenericArray/C.class new file mode 100644 index 0000000000000000000000000000000000000000..27903564a63e3a08c332282492d21f5c9f1fa959 GIT binary patch literal 263 zcmXX=yN<#z5S)dOK!D@X&{6^gY3M*mcaflppa9W3!2+Y;NG2fhSyU%o!3XeBC)PmW z^~~(->^}bg?f^z;`zWH}q3NMTpqNmMe#QiMqO{7VOndze!3ndiBs3zW<>GvdrCEzO zWu+ZuiAXoXD9b;hlke5ZCWV~jud=gACoa+e literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetGenericArray/NondetGenericArray.class b/regression/cbmc-java/NondetGenericArray/NondetGenericArray.class new file mode 100644 index 0000000000000000000000000000000000000000..76c6f43ab08f3eaa6fce6ec960d629d4d1acbb07 GIT binary patch literal 953 zcmZWn+fGwK6kXGnPJ4QQLb;RzqKI0mQZIM~wWVG{tZ0J4h)>hg2@D?2A=6V56a5i> zz-N^R(L{aH#E~QU}WS8h2Gg)LdC-V5m1JxzptIObl^rTi!S!?lX zj(Tkh<TLW0jep5U0zB1PhcXpiF5Zl5=8hso^ z8y9eqdRJ^*!eyJ}xx#VP#x-2$xMAZa=4|w!mmzClMOS!h#qxg*?rH67;?#Kw$GnYO zAU)CtxW}~(=>(*ruh)vsmiD)$E>@m|mZ8TB$v;!U`cl(%Nsjz<^(dIw$LR^0o5U@a zUo}#*n$cx}PS^r1VWP5$%2cAffP{^_SfsZ&=v8s42g6WZHk6k2HXqV8Xwm__;VS)$ z6nzwcrL#r>@}jgzHV|X-iewqtuEHMJJ8~k(&>jzy{TLwM{#SrO3{jN8a2x!Kstx$f zJ|f=`eOUMo9(#*ebRV(8F1n6{yNGvYcEJxN-y^YuL4&2@A4q*h^7$UDuVFsh$`jn<_@AK1XX1)^GH3jFwn;iKR;{ pQ)0OswHs@5oeh}+ef_DAuyGTdyCvPg=Fj)?BzW)x_@Sh; z)q$CL@5dXMpWm-<0FRg?2yhwWDn>?#o{Tl^GatUK43o*xdXS1Cda2{b26 zyw59Tclld+VBO*t19{IENlQ?6Br2Ef$?*OY^dVw^SY~vF0WL(Re*uh;h$D>8sq_Sy CYA+}N literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetGenericRecursive/B.class b/regression/cbmc-java/NondetGenericRecursive/B.class new file mode 100644 index 0000000000000000000000000000000000000000..8a18024f50bec9a3a4833f0bba7ce327a7d3c43f GIT binary patch literal 267 zcmXX=F;2rk5S)!28%)5#Ee$15;3i!V5{U$jWh6l9&zBXPWzN#Y&cCRTD0n~~g|Zi1 z?C#9$>}Yp?KfeHG$PxrdV@zY56G#z);$cpR?u<3vz0j-c6(L-kR$tPu!6u(uC)4VX=e!r^hmg^;3c1EvRH|}K4{CH4jl^{eU zKV*b~=V__zE`2QytZR(Xl1BlO3edSCIS}PWSSr)+IuDY^q45_Zf`-V4J~o<3KXhJr&7Ob}*6pb>7U- z@?u|v+d`{6K1-VEu1Xj>-YAX&nLd?~)XIM){Y)onD(?~Aflv`K`9$Ekl$hU2g}?t? z92O8HnxVSshi4+JtvJ)Ze4=v7-o>bQ_rz4#urbeZ%f@Z26TWN1!W>D-i%uw_9p~ZS zjUQ_rYlim4a2$Ob0}L4&=d&*+d(uzo-D17t_=h^4O6|BW3(K$&73;oH>Fy{CLx!dP z!25TYcCDZ1+>j1H8UmRpErXdhdW|%r0=@nit8~8_-IX;u`8MPk^wFXqPVyYGjBI&$ z4ECO!66*A?6v-wU2m7NFVUpHMvlH{ZcDKEnK8a1K&N N$$pTp)uo_>mETmHlY#&M literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetGenericRecursive/NondetGenericRecursive.java b/regression/cbmc-java/NondetGenericRecursive/NondetGenericRecursive.java new file mode 100644 index 00000000000..33d2b8d68bc --- /dev/null +++ b/regression/cbmc-java/NondetGenericRecursive/NondetGenericRecursive.java @@ -0,0 +1,24 @@ +import org.cprover.CProver; + +class A +{ +} + +class B +{ + A a; +} + +class C +{ + B b; +} + +class NondetGenericRecursive +{ + static void main() + { + C c = CProver.nondetWithNull(); + assert c == null; + } +} diff --git a/regression/cbmc-java/NondetGenericRecursive/test.desc b/regression/cbmc-java/NondetGenericRecursive/test.desc new file mode 100644 index 00000000000..34af1b2e6c1 --- /dev/null +++ b/regression/cbmc-java/NondetGenericRecursive/test.desc @@ -0,0 +1,6 @@ +CORE +NondetGenericRecursive.class +--function NondetGenericRecursive.main +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/cbmc-java/NondetGenericRecursive2/A.class b/regression/cbmc-java/NondetGenericRecursive2/A.class new file mode 100644 index 0000000000000000000000000000000000000000..5628564f73de76f1351bb4a729940bdd352fce99 GIT binary patch literal 250 zcmXYrPfNo<5XIj#|7?u5c=pg^?ZJR}Qwl}UOQ@iw_sw>&8{!7Gn|?1(LJxibKa@CI z9hjN-e!PMC{yBUBxWza}gtH9i8AgQk-dN-3glKxTCd3cjh6$s}SYGz;HM^CnTOk)! zr&YUF&IJDtW4|>!Ijt6Vg#5MZo#saq;+M)!3mo^P%jwO0jVBm`Oz z#=)1ZvTx;c-LUqUU?Bg6B54WAPDPcn14(9|pbrrPWHQqujBp~l_zPf&TpZ!_m@0k& D)om|Z literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetGenericRecursive2/B.class b/regression/cbmc-java/NondetGenericRecursive2/B.class new file mode 100644 index 0000000000000000000000000000000000000000..606067dcdb8b8be87b1a342f717de25a96a891fc GIT binary patch literal 268 zcmXX=!A`hx61^V)NQhC`(K<)Jn#X2lyMe& zn3?z9ym^_Q-|qu}JB(9wF-$N@a6uqN=;jYILOeIt_ETXsgjvaa3EG<Q|xn4=X~DRcj{nb7OhlYzuZD zswhPn=9O0EN;%{CMGWdMv-3%rB*pJl<228Vx8KbxyXN|hEjy!^tQ)s8dmcY+)LtbB z5y=x7Vc>aMD*Kr(iVf=;BedjGfTRL+E=UeUxe}Jj^t;aE59nJ!3tj2qNlXw6PR<7O L1o@!rlk4UPmB%o_ literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetGenericRecursive2/NondetGenericRecursive2.class b/regression/cbmc-java/NondetGenericRecursive2/NondetGenericRecursive2.class new file mode 100644 index 0000000000000000000000000000000000000000..ed328ac8e04844934c5d2ce66417ec021e5b92e6 GIT binary patch literal 879 zcmZ`%OHUI~6#h3fy?f<_F+?xxclxH!y^J5zoPOE<1n zB198)rHQ}E7|*Sx7z~Ru=W);DJKvd~zdwBeFpql{Y)o1>hbe*cMo*^^$AvUza4`)F zmjo_bNMTZ-V4;YTz!k#Kj1z`ZM=J2chbnX$o@^4RPDm~&UqufH@j`K(kf;VtNyyZc zFIQXJ4XIz4WWr!Aa2;>m(aQLpU?SR7Az{3>8u(2aJ(j-I%6%@~mJZdfoV(8rw;kp4 zD3>SHsvPKBiyZg$inG)1!AlTQ3$E8eVXXx%?aF0kW=@>ac6Q6zb!=pi6}W2S8fJMw z)kYcDZQQ_|z)hREx@Dse{e+xJFME!^QC>V^;gQyXCXAgjLEyHHJGe{89v44tY)Lm_ zG6TI)c6W5JD|Na0tgQ+Cew%}rD%xCac^+Z7P^_IS=KYg=iPko6mnhT?|F`WGaf+4FY literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetGenericRecursive2/NondetGenericRecursive2.java b/regression/cbmc-java/NondetGenericRecursive2/NondetGenericRecursive2.java new file mode 100644 index 00000000000..de5ef46c4cb --- /dev/null +++ b/regression/cbmc-java/NondetGenericRecursive2/NondetGenericRecursive2.java @@ -0,0 +1,27 @@ +import org.cprover.CProver; + +class A +{ +} + +class B +{ + A a; +} + +class C +{ + B b; +} + +class NondetGenericRecursive2 +{ + static void main() + { + C c = CProver.nondetWithNull(); + CProver.assume(c != null); + CProver.assume(c.b != null); + CProver.assume(c.b.a != null); + assert c.b.a != null; + } +} diff --git a/regression/cbmc-java/NondetGenericRecursive2/test.desc b/regression/cbmc-java/NondetGenericRecursive2/test.desc new file mode 100644 index 00000000000..52558889313 --- /dev/null +++ b/regression/cbmc-java/NondetGenericRecursive2/test.desc @@ -0,0 +1,6 @@ +CORE +NondetGenericRecursive2.class +--function NondetGenericRecursive2.main +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/cbmc-java/NondetGenericWithNull/B.class b/regression/cbmc-java/NondetGenericWithNull/B.class new file mode 100644 index 0000000000000000000000000000000000000000..80c9824e5191d58d4cea7551e4470546b0b1f6be GIT binary patch literal 264 zcmXX=yKcfj5S+!v4(4SjQ>6roxJd`104Y%<%M^)7eKsdJbU91roc~INM8OB-qY!(9 zVs~d|XCHr;(;2`Eh7mmUL&PBl1QHzYgkYwOvU7qr8m|fdvfM~QKUGF%^>;3-Pmya@ zhG|&{y%v>n{4V--rw%-tE~bR&qpYh!zA9&b%u2J7_DvdDsp3o7T~=%Tyca*Bg8(5P zUl3x)6D`a(S>=0KSUjP@UjoG8qj^U>z{&%&gsbZ{Cr8jPg9cihgPZ6fV%+&Rpv}lF I>fT(vD{ZJRegFUf literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetGenericWithNull/NondetGenericWithNull.class b/regression/cbmc-java/NondetGenericWithNull/NondetGenericWithNull.class new file mode 100644 index 0000000000000000000000000000000000000000..0b52a47bd0a58b584da059f5eddecf2f327ffbd8 GIT binary patch literal 772 zcmZuuOK;Oa5dJoHvWe@qshhS*DNvw55+J_xMuni^A%qD?MMdn@{QdbWfK9j-EUZ~Lj|&_ZD=1@~KEB#2FHti5$+1Dvim4$rUxovSn+ys6v*_EjHFinOO+n<24Q%c;Esffh^SBa-Zmv> zcT(ZMekzW01QO0r-txnd25ToCXkR{58RP1ipq)c;B5cfJj^nzGCRzl)ZDR&DLp>|H zp@{a~dt<*3w2rlnHf}I1oe9Zt)5a}y7^>6$XZ=Izr}T5N-go_D9iK?;cAw`b!(5ab z9y?{IHCx`l&19DeT94^Jr?qZKqhMGLWTLbTCOYY3(g77{4trRqaauHHR;_2wC^Be~ zX%H4gE}e|dV*3>AEd>QsX)pavVu50N6gya?TN$-Ub4stXX7>{c-(fs?2Xlz|_7BW_ zLGjfoO5gH~)BXTHoF+3GBd2j-Qd|KijSbS*A+j+gr;#jSnd&R~o5C+NIO;W0(3mLL j%=v)@r~DC>A-MSlrtu!;|5h@TA`151%{33>Kt$uhkTRanzciT3Vd{N$hn_E*$_bQESRQ0Lc+O{rlwVrOoR`d`d z=KBl6$n#VS^Odg3jjSB*(BVe`;t0{bARb`lido9l_qvaJ(2hX|*PNrX7$9NX`#0c* Kkzdq5y9OtR#xU6c literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetGenericWithoutNull/NondetGenericWithoutNull.class b/regression/cbmc-java/NondetGenericWithoutNull/NondetGenericWithoutNull.class new file mode 100644 index 0000000000000000000000000000000000000000..c369eae01fc067d724c1b3f4ba974f4e798d47ec GIT binary patch literal 740 zcmZ`%%Wl&^6g?9=nZ$LQM@vak3T-Kn1PO1tqe9T|SP(*`q9U@J*rRreYgc2tAJZRT z4M-G$1niLbCWN?S(iDNZu;)I{xo7VD`1R=vfDPPsP{EReD_G{ZS^>v3jui(*EOD$l zSi^OWb%yzMkt9;5DvpweDiPyQ1`KS(P})?HO7AgPo$fA!-H!vwP#vg94zt6t)Gtgi zLt_y8BHR^P8GjPA(|wgNvUBmSLgO z9sJu*lB?&jen^{OSPW#Mv<#*L(xs#sC1?#Jtk5DWv|v_i8cAeX^pRRH%#r2M$>=Qh zPQl)iQ9zacr9VN`$aW`o9S!ozn4dO}sM<8QKcesr*3);ePf+cB$INFGU!9`#)gW3q z;#^K_-j#zE4RVIe32yCZmnr}N literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetGenericWithoutNull/NondetGenericWithoutNull.java b/regression/cbmc-java/NondetGenericWithoutNull/NondetGenericWithoutNull.java new file mode 100644 index 00000000000..6a3ef4ad6f3 --- /dev/null +++ b/regression/cbmc-java/NondetGenericWithoutNull/NondetGenericWithoutNull.java @@ -0,0 +1,12 @@ +import org.cprover.CProver; + +class B { int a; } + +class NondetGenericWithoutNull +{ + static void main() + { + B b = CProver.nondetWithoutNull(); + assert b != null; + } +} diff --git a/regression/cbmc-java/NondetGenericWithoutNull/test.desc b/regression/cbmc-java/NondetGenericWithoutNull/test.desc new file mode 100644 index 00000000000..e9ada8b935c --- /dev/null +++ b/regression/cbmc-java/NondetGenericWithoutNull/test.desc @@ -0,0 +1,6 @@ +CORE +NondetGenericWithoutNull.class +--function NondetGenericWithoutNull.main +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/cbmc-java/NondetInt/NondetInt.class b/regression/cbmc-java/NondetInt/NondetInt.class new file mode 100644 index 0000000000000000000000000000000000000000..0af2adcb60811e4da89d1fc4900955c147598059 GIT binary patch literal 653 zcmZWmO;6iE5PcInvE!H|gf;{U<+CmAp}uefRjtxiLJA)e1qp5&dj$)|Mr#N0SKtry z+*T@8E4BCjrmE_!m4riOjc0b}&6_u~zyE&!31A&-9$d_Ln8l+iDwuOH@4?25gU22g zu;^fkFtsYOOzK>vN%mG{q94nMK*xm2rb<-)ieRlhKP1@QG?IiyPbG3^aM73gg8>s- zy)+c@q0q{lhnIGKsxm^Yx05E3%(s$!gDEbAN|^kbZHq9mpNsH(TU-un+|4i^w)FPX zfez(+Wg67S952trmGDu6?_k--3RZno;So9}5yT=n3Eqsxd8c)%3Dt46gC{Q0IT8xU|sV*gzS8CMMatXpM^x7;SRX z-%#544C@w+*&Eb;z&^S|`In)y3c7mH)#2B7(PkYZS{qaRJz(5JHg5U{Z7MJ$ed|R7 hV6s*D3g;G%{SmhH1=jys4MiCx|FxNDnhzy({sAPYctrpJ literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetInt/NondetInt.java b/regression/cbmc-java/NondetInt/NondetInt.java new file mode 100644 index 00000000000..f2ae6890fb0 --- /dev/null +++ b/regression/cbmc-java/NondetInt/NondetInt.java @@ -0,0 +1,10 @@ +import org.cprover.CProver; + +class NondetInt +{ + static void main() + { + int x = CProver.nondetInt(); + assert x == 0; + } +} diff --git a/regression/cbmc-java/NondetInt/test.desc b/regression/cbmc-java/NondetInt/test.desc new file mode 100644 index 00000000000..324d69b8c91 --- /dev/null +++ b/regression/cbmc-java/NondetInt/test.desc @@ -0,0 +1,6 @@ +CORE +NondetInt.class +--function NondetInt.main +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/cbmc-java/NondetLong/NondetLong.class b/regression/cbmc-java/NondetLong/NondetLong.class new file mode 100644 index 0000000000000000000000000000000000000000..27a693dee6ecb161b060f2971d1277c321b4ac0d GIT binary patch literal 659 zcmZWmOK;Oa5dOw?V#hVjqqHPEN`b!MfG@pK@lb#R3I(aCh~75#Ds1a|tF=?{L%7gC zz!{Jz0txQ?CWM%^(&WHlc4lY4`M#Oi-+#aV1h9q85CM82F5^lAbzJpvErf@jkL3{8 zvEt(fVPRDig*2todGS~kVwlO4K>LLHw#rp`pWtrZ-XnN@ok~J;pmMo0J{n5%%7O`< zflfrWCycW9NzyCds)7&=c66S~a-j3kJ?1zPDrfe0Y|jW6c1w{QJ{QN6qF_78CYs@{ z9-BlyRaT)nBe{DZPDF$`L_TgtxP{dS4TOZQeTXxWkK#w?13fWD8$viM_pugX9UFw! z4F6(yAd`|;q0J~xj*UK%ChotiJXhz_3940a-_2QVKjZZgmQq}ZI&aKjb{MwfTNf_v9H}Z1AXGa!91V!D(Rxhv4t`KEwtGO=uC@W^OriD z>wSas;4|D)w3i$2KVa?$yfdS#Vk!l kwkmm`-Kl?te+u9G2+#cj_y2A!MGa2$(9U#;FAlo@0PQ+@mH+?% literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetLong/NondetLong.java b/regression/cbmc-java/NondetLong/NondetLong.java new file mode 100644 index 00000000000..57707eb07cb --- /dev/null +++ b/regression/cbmc-java/NondetLong/NondetLong.java @@ -0,0 +1,10 @@ +import org.cprover.CProver; + +class NondetLong +{ + static void main() + { + long x = CProver.nondetLong(); + assert x == 0; + } +} diff --git a/regression/cbmc-java/NondetLong/test.desc b/regression/cbmc-java/NondetLong/test.desc new file mode 100644 index 00000000000..f92db994e00 --- /dev/null +++ b/regression/cbmc-java/NondetLong/test.desc @@ -0,0 +1,6 @@ +CORE +NondetLong.class +--function NondetLong.main +^VERIFICATION FAILED$ +-- +^warning: ignoring diff --git a/regression/cbmc-java/NondetShort/NondetShort.class b/regression/cbmc-java/NondetShort/NondetShort.class new file mode 100644 index 0000000000000000000000000000000000000000..32e0868de3ed525ffab450275ba48c87d4ef40ca GIT binary patch literal 661 zcmZWn%Wl&^6g?9=vFn&7O(9Lot3ZLm0&lu&g+KvTp&$h+wY!NuYNxn%HFhd~h5i6* zK%xjF*z-*YamGrTO2``DJ9E!D_c8PP@AsboHn1MR$8vxbT%AJ$*F0Pg;9}XsjQ}^X z>fx5a;+iZ9WlEiA#WP*VQK}LFu_w^j(wQzF3pnc!b_Cpho+yFVKxb-ud^A$#jRgyI z26-&g9ci@PPY&JkKoA65gQd4-ipOWf4Z`v>}Fd-VVS literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/NondetShort/NondetShort.java b/regression/cbmc-java/NondetShort/NondetShort.java new file mode 100644 index 00000000000..941ee23ffd2 --- /dev/null +++ b/regression/cbmc-java/NondetShort/NondetShort.java @@ -0,0 +1,10 @@ +import org.cprover.CProver; + +class NondetShort +{ + static void main() + { + short x = CProver.nondetShort(); + assert x == 0; + } +} diff --git a/regression/cbmc-java/NondetShort/test.desc b/regression/cbmc-java/NondetShort/test.desc new file mode 100644 index 00000000000..24ac39c540b --- /dev/null +++ b/regression/cbmc-java/NondetShort/test.desc @@ -0,0 +1,6 @@ +CORE +NondetShort.class +--function NondetShort.main +^VERIFICATION FAILED$ +-- +^warning: ignoring From f85494b07d4610767a55aa65ac9ad39690669de0 Mon Sep 17 00:00:00 2001 From: reuk Date: Tue, 28 Mar 2017 11:18:41 +0100 Subject: [PATCH 194/699] Add remove_java_nondet Use specialised member functions instead of `get` Fix indentation Remove insert_before --- src/cbmc/cbmc_parse_options.cpp | 16 ++ src/goto-programs/Makefile | 1 + src/goto-programs/remove_java_nondet.cpp | 330 +++++++++++++++++++++++ src/goto-programs/remove_java_nondet.h | 39 +++ 4 files changed, 386 insertions(+) create mode 100644 src/goto-programs/remove_java_nondet.cpp create mode 100644 src/goto-programs/remove_java_nondet.h diff --git a/src/cbmc/cbmc_parse_options.cpp b/src/cbmc/cbmc_parse_options.cpp index 1619143ce6c..9d36e749cf9 100644 --- a/src/cbmc/cbmc_parse_options.cpp +++ b/src/cbmc/cbmc_parse_options.cpp @@ -41,6 +41,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include #include #include @@ -53,6 +54,8 @@ Author: Daniel Kroening, kroening@kroening.com #include +#include "java_bytecode/java_bytecode_language.h" + #include "cbmc_solvers.h" #include "cbmc_parse_options.h" #include "bmc.h" @@ -921,6 +924,19 @@ bool cbmc_parse_optionst::process_goto_program( remove_complex(symbol_table, goto_functions); rewrite_union(goto_functions, ns); + // Similar removal of java nondet statements: + // TODO Should really get this from java_bytecode_language somehow, but we + // don't have an instance of that here. + const auto max_nondet_array_length= + cmdline.isset("java-max-input-array-length") + ? std::stoi(cmdline.get_value("java-max-input-array-length")) + : MAX_NONDET_ARRAY_LENGTH_DEFAULT; + remove_java_nondet( + ui_message_handler, + symbol_table, + max_nondet_array_length, + goto_functions); + // add generic checks status() << "Generic Property Instrumentation" << eom; goto_check(ns, options, goto_functions); diff --git a/src/goto-programs/Makefile b/src/goto-programs/Makefile index 6b2832e3481..da3e3e63628 100644 --- a/src/goto-programs/Makefile +++ b/src/goto-programs/Makefile @@ -25,6 +25,7 @@ SRC = goto_convert.cpp goto_convert_function_call.cpp \ remove_const_function_pointers.cpp \ system_library_symbols.cpp \ string_refine_preprocess.cpp \ + remove_java_nondet.cpp \ # Empty last line INCLUDES= -I .. diff --git a/src/goto-programs/remove_java_nondet.cpp b/src/goto-programs/remove_java_nondet.cpp new file mode 100644 index 00000000000..86962fddc64 --- /dev/null +++ b/src/goto-programs/remove_java_nondet.cpp @@ -0,0 +1,330 @@ +/*******************************************************************\ + +Module: Remove Java Nondet expressions + +Author: Reuben Thomas, reuben.thomas@diffblue.com + +\*******************************************************************/ + +#include "goto-programs/remove_java_nondet.h" +#include "goto-programs/goto_convert.h" +#include "goto-programs/goto_model.h" + +#include "java_bytecode/java_object_factory.h" + +#include "util/irep_ids.h" + +#include +#include + +/*******************************************************************\ + + Struct: nondet_instruction_infot + + Purpose: Hold information about a nondet instruction invocation. + +\*******************************************************************/ + +struct nondet_instruction_infot final +{ + bool is_nondet_instruction; + bool is_never_null; +}; + +/*******************************************************************\ + +Function: is_nondet_returning_object + + Inputs: + function_call: A function call expression. + + Outputs: Whether the function has a nondet signature, and whether the nondet + item may be null. + + + Purpose: Find whether the supplied function call has a recognised 'nondet' + library signature. If so, specify whether the function call is + expected to return non-null. + +\*******************************************************************/ + +static nondet_instruction_infot is_nondet_returning_object( + const code_function_callt &function_call) +{ + const auto &function_symbol=to_symbol_expr(function_call.function()); + const auto function_name=id2string(function_symbol.get_identifier()); + std::smatch match_results; + if(!std::regex_match( + function_name, + match_results, + std::regex(".*org\\.cprover\\.CProver\\.nondetWith(out)?Null.*"))) + { + return {false, false}; + } + + return {true, match_results[1].matched}; +} + +/*******************************************************************\ + +Function: get_nondet_instruction_info + + Inputs: + instr: A goto program instruction. + + Outputs: Whether the instruction is a function with a nondet signature, and + whether the nondet item may be null. + + Purpose: Return whether the instruction has a recognised 'nondet' library + signature. + +\*******************************************************************/ + +static nondet_instruction_infot get_nondet_instruction_info( + const goto_programt::targett &instr) +{ + if(!(instr->is_function_call() && instr->code.id()==ID_code)) + { + return {false, false}; + } + const auto &code=to_code(instr->code); + if(code.get_statement()!=ID_function_call) + { + return {false, false}; + } + const auto &function_call=to_code_function_call(code); + return is_nondet_returning_object(function_call); +} + +/*******************************************************************\ + +Function: is_symbol_with_id + + Inputs: + expr: The expression which may be a symbol. + identifier: Some identifier. + + Outputs: True if the expression is a symbol with the specified identifier. + + Purpose: Return whether the expression is a symbol with the specified + identifier. + +\*******************************************************************/ + +static bool is_symbol_with_id(const exprt& expr, const dstringt& identifier) +{ + return expr.id()==ID_symbol && + to_symbol_expr(expr).get_identifier()==identifier; +} + +/*******************************************************************\ + +Function: is_typecast_with_id + + Inputs: + expr: The expression which may be a typecast. + identifier: Some identifier. + + Outputs: True if the expression is a typecast with one operand, and the + typecast's identifier matches the specified identifier. + + Purpose: Return whether the expression is a typecast with the specified + identifier. + +\*******************************************************************/ + +static bool is_typecast_with_id(const exprt& expr, const dstringt& identifier) +{ + if(!(expr.id()==ID_typecast && expr.operands().size()==1)) + { + return false; + } + const auto &typecast=to_typecast_expr(expr); + if(!(typecast.op().id()==ID_symbol && !typecast.op().has_operands())) + { + return false; + } + const auto &op_symbol=to_symbol_expr(typecast.op()); + // Return whether the typecast has the expected operand + return op_symbol.get_identifier()==identifier; +} + +/*******************************************************************\ + +Function: is_assignment_from + + Inputs: + instr: A goto program instruction. + identifier: Some identifier. + + Outputs: True if the expression is a typecast with one operand, and the + typecast's identifier matches the specified identifier. + + Purpose: Return whether the instruction is an assignment, and the rhs is a + symbol or typecast expression with the specified identifier. + +\*******************************************************************/ + +static bool is_assignment_from( + const goto_programt::instructiont &instr, + const dstringt &identifier) +{ + // If not an assignment, return false + if(!instr.is_assign()) + { + return false; + } + const auto &rhs=to_code_assign(instr.code).rhs(); + return is_symbol_with_id(rhs, identifier) || + is_typecast_with_id(rhs, identifier); +} + +/*******************************************************************\ + +Function: process_target + + Inputs: + message_handler: Handles logging. + symbol_table: The table of known symbols. + max_nondet_array_length: Max length of arrays in new nondet objects. + instructions: The list of all instructions. + instr: The instruction to check. + + Outputs: The next instruction to process, probably with this function. + + Purpose: Given an iterator into a list of instructions, modify the list to + replace 'nondet' library functions with CBMC-native nondet + expressions, and return an iterator to the next instruction to check. + +\*******************************************************************/ + +static goto_programt::targett process_target( + message_handlert &message_handler, + symbol_tablet &symbol_table, + const size_t max_nondet_array_length, + goto_programt &prog, + const goto_programt::targett &instr) +{ + // Check whether this is our nondet library method, and return if not + const auto instr_info=get_nondet_instruction_info(instr); + const auto next_instr=std::next(instr); + if(!instr_info.is_nondet_instruction) + { + return next_instr; + } + + // Look at the next instruction, ensure that it is an assignment + assert(next_instr->is_assign()); + // Get the name of the LHS of the assignment + const auto &next_instr_assign_lhs=to_code_assign(next_instr->code).lhs(); + if(!(next_instr_assign_lhs.id()==ID_symbol && + !next_instr_assign_lhs.has_operands())) + { + return next_instr; + } + const auto return_identifier= + to_symbol_expr(next_instr_assign_lhs).get_identifier(); + + auto &instructions=prog.instructions; + const auto end=std::end(instructions); + + // Look for an instruction where this name is on the RHS of an assignment + const auto matching_assignment=std::find_if( + next_instr, + end, + [&return_identifier](const goto_programt::instructiont &instr) + { + return is_assignment_from(instr, return_identifier); + }); + + assert(matching_assignment!=end); + + // Assume that the LHS of *this* assignment is the actual nondet variable + const auto &code_assign=to_code_assign(matching_assignment->code); + const auto nondet_var=code_assign.lhs(); + const auto source_loc=instr->source_location; + + // Erase from the nondet function call to the assignment + const auto after_matching_assignment=std::next(matching_assignment); + assert(after_matching_assignment!=end); + const auto after_erased= + instructions.erase(instr, after_matching_assignment); + + // Generate nondet init code + code_blockt init_code; + gen_nondet_init( + nondet_var, + init_code, + symbol_table, + source_loc, + false, + true, + instr_info.is_never_null, + message_handler, + max_nondet_array_length); + + // Convert this code into goto instructions + goto_programt new_instructions; + goto_convert(init_code, symbol_table, new_instructions, message_handler); + + // Insert the new instructions into the instruction list + prog.destructive_insert(after_erased, new_instructions); + prog.update(); + + return after_erased; +} + +/*******************************************************************\ + +Function: remove_java_nondet + + Inputs: + message_handler: Object which prints messages. + symbol_table: The list of known symbols. + max_nondet_array_length: The maximum length of new nondet arrays. + goto_program: The program to modify. + + Purpose: Modify a goto_programt to replace 'nondet' library functions with + CBMC-native nondet expressions. + +\*******************************************************************/ + +static void remove_java_nondet( + message_handlert &message_handler, + symbol_tablet &symbol_table, + const size_t max_nondet_array_length, + goto_programt &goto_program) +{ + // Check each instruction. + // `process_target` may modify the list in place, and returns the next + // iterator to look at. + for(auto instruction_iterator=std::begin(goto_program.instructions), + end=std::end(goto_program.instructions); + instruction_iterator!=end; + instruction_iterator=process_target( + message_handler, + symbol_table, + max_nondet_array_length, + goto_program, + instruction_iterator)) + { + // Loop body deliberately empty. + } +} + +void remove_java_nondet( + message_handlert &message_handler, + symbol_tablet &symbol_table, + const size_t max_nondet_array_length, + goto_functionst &goto_functions) +{ + for(auto &f : goto_functions.function_map) + { + remove_java_nondet( + message_handler, + symbol_table, + max_nondet_array_length, + f.second.body); + } + goto_functions.compute_location_numbers(); +} diff --git a/src/goto-programs/remove_java_nondet.h b/src/goto-programs/remove_java_nondet.h new file mode 100644 index 00000000000..0af514b5b11 --- /dev/null +++ b/src/goto-programs/remove_java_nondet.h @@ -0,0 +1,39 @@ +/*******************************************************************\ + +Module: Remove Java Nondet expressions + +Author: Reuben Thomas, reuben.thomas@diffblue.com + +\*******************************************************************/ + +#ifndef CPROVER_GOTO_PROGRAMS_REMOVE_JAVA_NONDET_H +#define CPROVER_GOTO_PROGRAMS_REMOVE_JAVA_NONDET_H + +#include // size_t + +class message_handlert; +class symbol_tablet; +class goto_functionst; + +/*******************************************************************\ + +Function: remove_java_nondet + + Inputs: + message_handler: Object which prints instructions. + symbol_table: The list of known symbols. + max_nondet_array_length: The maximum length of new nondet arrays. + goto_functions: The set of goto programs to modify. + + Purpose: Modify a goto_functionst to replace 'nondet' library functions with + CBMC-native nondet expressions. + +\*******************************************************************/ + +void remove_java_nondet( + message_handlert &message_handler, + symbol_tablet &symbol_table, + size_t max_nondet_array_length, + goto_functionst &goto_functions); + +#endif From 19c8d8d7c85cad8689772f6c87ac49ff96cfe713 Mon Sep 17 00:00:00 2001 From: reuk Date: Tue, 28 Mar 2017 11:04:21 +0100 Subject: [PATCH 195/699] Suppress loading methods with nondet signatures --- .../java_bytecode_convert_method.cpp | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 4888810bd83..65696e7877a 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -31,6 +31,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include class patternt { @@ -2531,6 +2532,29 @@ void java_bytecode_convert_method( safe_pointer > needed_methods, safe_pointer > needed_classes) { + static const std::unordered_set methods_to_ignore + { + "nondetBoolean", + "nondetByte", + "nondetChar", + "nondetShort", + "nondetInt", + "nondetLong", + "nondetFloat", + "nondetDouble", + "nondetWithNull", + "nondetWithoutNull", + }; + + if(std::regex_match( + id2string(class_symbol.name), + std::regex(".*org\\.cprover\\.CProver.*")) && + methods_to_ignore.find(id2string(method.name))!=methods_to_ignore.end()) + { + // Ignore these methods, rely on default stubbing behaviour. + return; + } + java_bytecode_convert_methodt java_bytecode_convert_method( symbol_table, message_handler, From dc94557d87a310d4bdf1e848f8eafc8f0ac61cca Mon Sep 17 00:00:00 2001 From: reuk Date: Tue, 4 Apr 2017 17:00:52 +0100 Subject: [PATCH 196/699] Rearrange loop in remove_java_nondet --- src/goto-programs/remove_java_nondet.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/goto-programs/remove_java_nondet.cpp b/src/goto-programs/remove_java_nondet.cpp index 86962fddc64..ce1543ab7f3 100644 --- a/src/goto-programs/remove_java_nondet.cpp +++ b/src/goto-programs/remove_java_nondet.cpp @@ -298,17 +298,18 @@ static void remove_java_nondet( // Check each instruction. // `process_target` may modify the list in place, and returns the next // iterator to look at. + // Can't use forall_goto_program_instructions because we don't want to + // increment the iterator by one after every iteration. for(auto instruction_iterator=std::begin(goto_program.instructions), end=std::end(goto_program.instructions); - instruction_iterator!=end; - instruction_iterator=process_target( - message_handler, - symbol_table, - max_nondet_array_length, - goto_program, - instruction_iterator)) + instruction_iterator!=end;) { - // Loop body deliberately empty. + instruction_iterator=process_target( + message_handler, + symbol_table, + max_nondet_array_length, + goto_program, + instruction_iterator); } } From 17db86df0814e6a24b1e7fbc749041d676246a28 Mon Sep 17 00:00:00 2001 From: Owen Jones Date: Thu, 13 Apr 2017 15:33:06 +0100 Subject: [PATCH 197/699] Refactor java object factory Functionally equivalent, but uses RAII. Also more concise. Makes code match master, which will make merging easier. --- src/java_bytecode/java_object_factory.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index 55dfc96931f..36fa819c979 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -464,19 +464,12 @@ void java_object_factoryt::gen_nondet_init( } else { - code_assignt assign; - assign.lhs()=expr; + exprt rhs=type.id()==ID_c_bool? + get_nondet_bool(type): + side_effect_expr_nondett(type); + code_assignt assign(expr, rhs); assign.add_source_location()=loc; - if(type.id()==ID_c_bool) - { - assign.rhs()=get_nondet_bool(type); - } - else - { - assign.rhs()=side_effect_expr_nondett(type); - } - init_code.copy_to_operands(assign); } } From df1caca1e96fd3c2144e94da27a14206f06e4eda Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Mon, 10 Apr 2017 13:38:49 +0100 Subject: [PATCH 198/699] Adding namespace to arguments of from_expr in debug diffblue/test-gen#201 Not finding a symbol in from_expr can cause some exception to be thrown. This was happening while outputing debug information in some examples when --refine-strings was activated. --- src/solvers/refinement/string_refinement.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/solvers/refinement/string_refinement.cpp b/src/solvers/refinement/string_refinement.cpp index 6cd090d4b1d..eeb8788bceb 100644 --- a/src/solvers/refinement/string_refinement.cpp +++ b/src/solvers/refinement/string_refinement.cpp @@ -475,8 +475,8 @@ void string_refinementt::set_to(const exprt &expr, bool value) // Preprocessing to remove function applications. const exprt &lhs=eq_expr.lhs(); - debug() << "(sr::set_to) " << from_expr(lhs) - << " = " << from_expr(eq_expr.rhs()) << eom; + debug() << "(sr::set_to) " << from_expr(ns, "", lhs) + << " = " << from_expr(ns, "", eq_expr.rhs()) << eom; // TODO: See if this happens at all. if(lhs.id()!=ID_symbol) @@ -545,7 +545,7 @@ decision_proceduret::resultt string_refinementt::dec_solve() for(std::pair &pair : non_string_axioms) { replace_expr(symbol_resolve, pair.first); - debug() << "super::set_to " << from_expr(pair.first) << eom; + debug() << "super::set_to " << from_expr(ns, "", pair.first) << eom; supert::set_to(pair.first, pair.second); } From f4a47f9e1d64b013d054f0ae0529200c222b2bd7 Mon Sep 17 00:00:00 2001 From: reuk Date: Wed, 5 Apr 2017 12:01:39 +0100 Subject: [PATCH 199/699] Split java nondet pass in two --- src/cbmc/cbmc_parse_options.cpp | 12 +- src/goto-programs/Makefile | 3 +- src/goto-programs/convert_nondet.cpp | 164 ++++++++++++++ ...{remove_java_nondet.h => convert_nondet.h} | 30 +-- ...ava_nondet.cpp => replace_java_nondet.cpp} | 206 +++++++++--------- src/goto-programs/replace_java_nondet.h | 28 +++ src/util/irep_ids.txt | 3 +- src/util/std_code.h | 27 +++ 8 files changed, 342 insertions(+), 131 deletions(-) create mode 100644 src/goto-programs/convert_nondet.cpp rename src/goto-programs/{remove_java_nondet.h => convert_nondet.h} (51%) rename src/goto-programs/{remove_java_nondet.cpp => replace_java_nondet.cpp} (58%) create mode 100644 src/goto-programs/replace_java_nondet.h diff --git a/src/cbmc/cbmc_parse_options.cpp b/src/cbmc/cbmc_parse_options.cpp index 9d36e749cf9..2c5806ed868 100644 --- a/src/cbmc/cbmc_parse_options.cpp +++ b/src/cbmc/cbmc_parse_options.cpp @@ -41,7 +41,8 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include -#include +#include +#include #include #include @@ -931,11 +932,12 @@ bool cbmc_parse_optionst::process_goto_program( cmdline.isset("java-max-input-array-length") ? std::stoi(cmdline.get_value("java-max-input-array-length")) : MAX_NONDET_ARRAY_LENGTH_DEFAULT; - remove_java_nondet( - ui_message_handler, + replace_java_nondet(goto_functions); + convert_nondet( + goto_functions, symbol_table, - max_nondet_array_length, - goto_functions); + ui_message_handler, + max_nondet_array_length); // add generic checks status() << "Generic Property Instrumentation" << eom; diff --git a/src/goto-programs/Makefile b/src/goto-programs/Makefile index da3e3e63628..e873310b0c7 100644 --- a/src/goto-programs/Makefile +++ b/src/goto-programs/Makefile @@ -25,7 +25,8 @@ SRC = goto_convert.cpp goto_convert_function_call.cpp \ remove_const_function_pointers.cpp \ system_library_symbols.cpp \ string_refine_preprocess.cpp \ - remove_java_nondet.cpp \ + replace_java_nondet.cpp \ + convert_nondet.cpp \ # Empty last line INCLUDES= -I .. diff --git a/src/goto-programs/convert_nondet.cpp b/src/goto-programs/convert_nondet.cpp new file mode 100644 index 00000000000..148323c1d67 --- /dev/null +++ b/src/goto-programs/convert_nondet.cpp @@ -0,0 +1,164 @@ +/*******************************************************************\ + +Module: Convert side_effect_expr_nondett expressions + +Author: Reuben Thomas, reuben.thomas@diffblue.com + +\*******************************************************************/ + +#include "goto-programs/convert_nondet.h" +#include "goto-programs/goto_convert.h" +#include "goto-programs/goto_model.h" + +#include "java_bytecode/java_object_factory.h" // gen_nondet_init + +#include "util/irep_ids.h" + +/*******************************************************************\ + +Function: insert_nondet_init_code + + Inputs: + goto_program: The goto program to modify. + target: One of the steps in that goto program. + symbol_table: The global symbol table. + message_handler: Handles logging. + max_nondet_array_length: Maximum size of new nondet arrays. + + Outputs: The next instruction to process with this function. + + Purpose: Checks an instruction to see whether it contains an assignment + from side_effect_expr_nondet. If so, replaces the instruction + with a range of instructions to properly nondet-initialize + the lhs. + +\*******************************************************************/ + +static goto_programt::const_targett insert_nondet_init_code( + goto_programt &goto_program, + const goto_programt::const_targett &target, + symbol_tablet &symbol_table, + message_handlert &message_handler, + size_t max_nondet_array_length) +{ + // Return if the instruction isn't an assignment + const auto next_instr=std::next(target); + if(!target->is_assign()) + { + return next_instr; + } + + // Return if the rhs of the assignment isn't a side effect expression + const auto &assign=to_code_assign(target->code); + if(assign.rhs().id()!=ID_side_effect) + { + return next_instr; + } + + // Return if the rhs isn't nondet + const auto &side_effect=to_side_effect_expr(assign.rhs()); + if(side_effect.get_statement()!=ID_nondet) + { + return next_instr; + } + + const auto lhs=assign.lhs(); + // If the lhs type doesn't have a subtype then I guess it's primitive and + // we want to bail out now + if(!lhs.type().has_subtype()) + { + return next_instr; + } + + // Although, if the type is a ptr-to-void then we also want to bail + if(lhs.type().subtype().id()==ID_empty) + { + return next_instr; + } + + // Check whether the nondet object may be null + const auto nullable=to_side_effect_expr_nondet(side_effect).get_nullable(); + // Get the symbol to nondet-init + const auto source_loc=target->source_location; + + // Erase the nondet assignment + const auto after_erased=goto_program.instructions.erase(target); + + // Generate nondet init code + code_blockt init_code; + gen_nondet_init( + lhs, + init_code, + symbol_table, + source_loc, + false, + true, + !nullable, + message_handler, + max_nondet_array_length); + + // Convert this code into goto instructions + goto_programt new_instructions; + goto_convert(init_code, symbol_table, new_instructions, message_handler); + + // Insert the new instructions into the instruction list + goto_program.destructive_insert(after_erased, new_instructions); + goto_program.update(); + + return after_erased; +} + +/*******************************************************************\ + +Function: convert_nondet + + Inputs: + goto_program: The goto program to modify. + symbol_table: The global symbol table. + message_handler: Handles logging. + max_nondet_array_length: Maximum size of new nondet arrays. + + Purpose: For each instruction in the goto program, checks if it is + an assignment from nondet and replaces it with the appropriate + composite initialization code if so. + +\*******************************************************************/ + +static void convert_nondet( + goto_programt &goto_program, + symbol_tablet &symbol_table, + message_handlert &message_handler, + size_t max_nondet_array_length) +{ + for(auto instruction_iterator=goto_program.instructions.cbegin(), + end=goto_program.instructions.cend(); + instruction_iterator!=end;) + { + instruction_iterator=insert_nondet_init_code( + goto_program, + instruction_iterator, + symbol_table, + message_handler, + max_nondet_array_length); + } +} + + + +void convert_nondet( + goto_functionst &goto_functions, + symbol_tablet &symbol_table, + message_handlert &message_handler, + size_t max_nondet_array_length) +{ + for(auto &goto_program : goto_functions.function_map) + { + convert_nondet( + goto_program.second.body, + symbol_table, + message_handler, + max_nondet_array_length); + } + + goto_functions.compute_location_numbers(); +} diff --git a/src/goto-programs/remove_java_nondet.h b/src/goto-programs/convert_nondet.h similarity index 51% rename from src/goto-programs/remove_java_nondet.h rename to src/goto-programs/convert_nondet.h index 0af514b5b11..919d977a94e 100644 --- a/src/goto-programs/remove_java_nondet.h +++ b/src/goto-programs/convert_nondet.h @@ -1,39 +1,39 @@ /*******************************************************************\ -Module: Remove Java Nondet expressions +Module: Convert side_effect_expr_nondett expressions Author: Reuben Thomas, reuben.thomas@diffblue.com \*******************************************************************/ -#ifndef CPROVER_GOTO_PROGRAMS_REMOVE_JAVA_NONDET_H -#define CPROVER_GOTO_PROGRAMS_REMOVE_JAVA_NONDET_H +#ifndef CPROVER_GOTO_PROGRAMS_CONVERT_NONDET_H +#define CPROVER_GOTO_PROGRAMS_CONVERT_NONDET_H #include // size_t -class message_handlert; -class symbol_tablet; class goto_functionst; +class symbol_tablet; +class message_handlert; /*******************************************************************\ -Function: remove_java_nondet +Function: convert_nondet Inputs: - message_handler: Object which prints instructions. - symbol_table: The list of known symbols. - max_nondet_array_length: The maximum length of new nondet arrays. goto_functions: The set of goto programs to modify. + symbol_table: The symbol table to query/update. + message_handler: For error logging. + max_nondet_array_length: The maximum length of any new arrays. - Purpose: Modify a goto_functionst to replace 'nondet' library functions with - CBMC-native nondet expressions. + Purpose: Replace calls to nondet library functions with an internal + nondet representation. \*******************************************************************/ -void remove_java_nondet( - message_handlert &message_handler, +void convert_nondet( + goto_functionst &goto_functions, symbol_tablet &symbol_table, - size_t max_nondet_array_length, - goto_functionst &goto_functions); + message_handlert &message_handler, + size_t max_nondet_array_length); #endif diff --git a/src/goto-programs/remove_java_nondet.cpp b/src/goto-programs/replace_java_nondet.cpp similarity index 58% rename from src/goto-programs/remove_java_nondet.cpp rename to src/goto-programs/replace_java_nondet.cpp index ce1543ab7f3..b78a0819cac 100644 --- a/src/goto-programs/remove_java_nondet.cpp +++ b/src/goto-programs/replace_java_nondet.cpp @@ -1,17 +1,15 @@ /*******************************************************************\ -Module: Remove Java Nondet expressions +Module: Replace Java Nondet expressions Author: Reuben Thomas, reuben.thomas@diffblue.com \*******************************************************************/ -#include "goto-programs/remove_java_nondet.h" +#include "goto-programs/replace_java_nondet.h" #include "goto-programs/goto_convert.h" #include "goto-programs/goto_model.h" -#include "java_bytecode/java_object_factory.h" - #include "util/irep_ids.h" #include @@ -19,16 +17,37 @@ Author: Reuben Thomas, reuben.thomas@diffblue.com /*******************************************************************\ - Struct: nondet_instruction_infot + Class: nondet_instruction_infot - Purpose: Hold information about a nondet instruction invocation. + Purpose: Holds information about any discovered nondet methods, + with extreme type-safety. \*******************************************************************/ -struct nondet_instruction_infot final +class nondet_instruction_infot final { - bool is_nondet_instruction; - bool is_never_null; +public: + enum class is_nondett:bool { FALSE, TRUE }; + enum class is_nullablet:bool { FALSE, TRUE }; + + nondet_instruction_infot(): + is_nondet(is_nondett::FALSE), + is_nullable(is_nullablet::FALSE) + { + } + + explicit nondet_instruction_infot(is_nullablet is_nullable): + is_nondet(is_nondett::TRUE), + is_nullable(is_nullable) + { + } + + is_nondett get_instruction_type() const { return is_nondet; } + is_nullablet get_nullable_type() const { return is_nullable; } + +private: + is_nondett is_nondet; + is_nullablet is_nullable; }; /*******************************************************************\ @@ -36,15 +55,14 @@ struct nondet_instruction_infot final Function: is_nondet_returning_object Inputs: - function_call: A function call expression. - - Outputs: Whether the function has a nondet signature, and whether the nondet - item may be null. + function_call: The function call declaration to check. + Outputs: A structure detailing whether the function call appears to + be one of our nondet library methods, and if so, whether + or not it allows null results. - Purpose: Find whether the supplied function call has a recognised 'nondet' - library signature. If so, specify whether the function call is - expected to return non-null. + Purpose: Checks whether the function call is one of our nondet + library functions. \*******************************************************************/ @@ -53,16 +71,17 @@ static nondet_instruction_infot is_nondet_returning_object( { const auto &function_symbol=to_symbol_expr(function_call.function()); const auto function_name=id2string(function_symbol.get_identifier()); + const std::regex reg( + R"(.*org\.cprover\.CProver\.nondet)" + R"((?:Boolean|Byte|Char|Short|Int|Long|Float|Double|With(out)?Null.*))"); std::smatch match_results; - if(!std::regex_match( - function_name, - match_results, - std::regex(".*org\\.cprover\\.CProver\\.nondetWith(out)?Null.*"))) + if(!std::regex_match(function_name, match_results, reg)) { - return {false, false}; + return nondet_instruction_infot(); } - return {true, match_results[1].matched}; + return nondet_instruction_infot( + nondet_instruction_infot::is_nullablet(!match_results[1].matched)); } /*******************************************************************\ @@ -70,27 +89,27 @@ static nondet_instruction_infot is_nondet_returning_object( Function: get_nondet_instruction_info Inputs: - instr: A goto program instruction. + instr: A goto-program instruction to check. - Outputs: Whether the instruction is a function with a nondet signature, and - whether the nondet item may be null. + Outputs: A structure detailing the properties of the nondet method. - Purpose: Return whether the instruction has a recognised 'nondet' library - signature. + Purpose: Check whether the instruction is a function call which + matches one of the recognised nondet library methods, and + return some information about it. \*******************************************************************/ static nondet_instruction_infot get_nondet_instruction_info( - const goto_programt::targett &instr) + const goto_programt::const_targett &instr) { if(!(instr->is_function_call() && instr->code.id()==ID_code)) { - return {false, false}; + return nondet_instruction_infot(); } const auto &code=to_code(instr->code); if(code.get_statement()!=ID_function_call) { - return {false, false}; + return nondet_instruction_infot(); } const auto &function_call=to_code_function_call(code); return is_nondet_returning_object(function_call); @@ -111,7 +130,7 @@ Function: is_symbol_with_id \*******************************************************************/ -static bool is_symbol_with_id(const exprt& expr, const dstringt& identifier) +static bool is_symbol_with_id(const exprt& expr, const irep_idt& identifier) { return expr.id()==ID_symbol && to_symbol_expr(expr).get_identifier()==identifier; @@ -133,7 +152,7 @@ Function: is_typecast_with_id \*******************************************************************/ -static bool is_typecast_with_id(const exprt& expr, const dstringt& identifier) +static bool is_typecast_with_id(const exprt& expr, const irep_idt& identifier) { if(!(expr.id()==ID_typecast && expr.operands().size()==1)) { @@ -167,7 +186,7 @@ Function: is_assignment_from static bool is_assignment_from( const goto_programt::instructiont &instr, - const dstringt &identifier) + const irep_idt &identifier) { // If not an assignment, return false if(!instr.is_assign()) @@ -181,14 +200,12 @@ static bool is_assignment_from( /*******************************************************************\ -Function: process_target +Function: check_and_replace_target Inputs: - message_handler: Handles logging. - symbol_table: The table of known symbols. - max_nondet_array_length: Max length of arrays in new nondet objects. - instructions: The list of all instructions. - instr: The instruction to check. + goto_program: The goto program to modify. + target: A single step of the goto program which may be erased and + replaced. Outputs: The next instruction to process, probably with this function. @@ -198,17 +215,15 @@ Function: process_target \*******************************************************************/ -static goto_programt::targett process_target( - message_handlert &message_handler, - symbol_tablet &symbol_table, - const size_t max_nondet_array_length, - goto_programt &prog, - const goto_programt::targett &instr) +static goto_programt::const_targett check_and_replace_target( + goto_programt &goto_program, + const goto_programt::const_targett &target) { - // Check whether this is our nondet library method, and return if not - const auto instr_info=get_nondet_instruction_info(instr); - const auto next_instr=std::next(instr); - if(!instr_info.is_nondet_instruction) + // Check whether this is a nondet library method, and return if not + const auto instr_info=get_nondet_instruction_info(target); + const auto next_instr=std::next(target); + if(instr_info.get_instruction_type()== + nondet_instruction_infot::is_nondett::FALSE) { return next_instr; } @@ -225,8 +240,8 @@ static goto_programt::targett process_target( const auto return_identifier= to_symbol_expr(next_instr_assign_lhs).get_identifier(); - auto &instructions=prog.instructions; - const auto end=std::end(instructions); + auto &instructions=goto_program.instructions; + const auto end=instructions.cend(); // Look for an instruction where this name is on the RHS of an assignment const auto matching_assignment=std::find_if( @@ -242,90 +257,63 @@ static goto_programt::targett process_target( // Assume that the LHS of *this* assignment is the actual nondet variable const auto &code_assign=to_code_assign(matching_assignment->code); const auto nondet_var=code_assign.lhs(); - const auto source_loc=instr->source_location; + const auto source_loc=target->source_location; // Erase from the nondet function call to the assignment const auto after_matching_assignment=std::next(matching_assignment); assert(after_matching_assignment!=end); - const auto after_erased= - instructions.erase(instr, after_matching_assignment); - - // Generate nondet init code - code_blockt init_code; - gen_nondet_init( - nondet_var, - init_code, - symbol_table, - source_loc, - false, - true, - instr_info.is_never_null, - message_handler, - max_nondet_array_length); - - // Convert this code into goto instructions - goto_programt new_instructions; - goto_convert(init_code, symbol_table, new_instructions, message_handler); - - // Insert the new instructions into the instruction list - prog.destructive_insert(after_erased, new_instructions); - prog.update(); + + const auto after_erased=goto_program.instructions.erase( + target, after_matching_assignment); + + const auto inserted=goto_program.insert_before(after_erased); + inserted->make_assignment(); + side_effect_expr_nondett inserted_expr(nondet_var.type()); + inserted_expr.set_nullable( + instr_info.get_nullable_type()== + nondet_instruction_infot::is_nullablet::TRUE); + inserted->code=code_assignt(nondet_var, inserted_expr); + inserted->code.add_source_location()=source_loc; + inserted->source_location=source_loc; + + goto_program.update(); return after_erased; } /*******************************************************************\ -Function: remove_java_nondet +Function: replace_java_nondet Inputs: - message_handler: Object which prints messages. - symbol_table: The list of known symbols. - max_nondet_array_length: The maximum length of new nondet arrays. - goto_program: The program to modify. + goto_program: The goto program to modify. - Purpose: Modify a goto_programt to replace 'nondet' library functions with - CBMC-native nondet expressions. + Purpose: Checks each instruction in the goto program to see whether + it is a method returning nondet. If it is, replaces the + function call with an irep representing a nondet side + effect with an appropriate type. \*******************************************************************/ -static void remove_java_nondet( - message_handlert &message_handler, - symbol_tablet &symbol_table, - const size_t max_nondet_array_length, - goto_programt &goto_program) +static void replace_java_nondet(goto_programt &goto_program) { - // Check each instruction. - // `process_target` may modify the list in place, and returns the next - // iterator to look at. - // Can't use forall_goto_program_instructions because we don't want to - // increment the iterator by one after every iteration. - for(auto instruction_iterator=std::begin(goto_program.instructions), - end=std::end(goto_program.instructions); + for(auto instruction_iterator=goto_program.instructions.cbegin(), + end=goto_program.instructions.cend(); instruction_iterator!=end;) { - instruction_iterator=process_target( - message_handler, - symbol_table, - max_nondet_array_length, + instruction_iterator=check_and_replace_target( goto_program, instruction_iterator); } } -void remove_java_nondet( - message_handlert &message_handler, - symbol_tablet &symbol_table, - const size_t max_nondet_array_length, - goto_functionst &goto_functions) + + +void replace_java_nondet(goto_functionst &goto_functions) { - for(auto &f : goto_functions.function_map) + for(auto &goto_program : goto_functions.function_map) { - remove_java_nondet( - message_handler, - symbol_table, - max_nondet_array_length, - f.second.body); + replace_java_nondet(goto_program.second.body); } goto_functions.compute_location_numbers(); } diff --git a/src/goto-programs/replace_java_nondet.h b/src/goto-programs/replace_java_nondet.h new file mode 100644 index 00000000000..077f95ab84c --- /dev/null +++ b/src/goto-programs/replace_java_nondet.h @@ -0,0 +1,28 @@ +/*******************************************************************\ + +Module: Replace Java Nondet expressions + +Author: Reuben Thomas, reuben.thomas@diffblue.com + +\*******************************************************************/ + +#ifndef CPROVER_GOTO_PROGRAMS_REPLACE_JAVA_NONDET_H +#define CPROVER_GOTO_PROGRAMS_REPLACE_JAVA_NONDET_H + +class goto_functionst; + +/*******************************************************************\ + +Function: replace_java_nondet + + Inputs: + goto_functions: The set of goto programs to modify. + + Purpose: Replace calls to nondet library functions with an internal + nondet representation. + +\*******************************************************************/ + +void replace_java_nondet(goto_functionst &goto_functions); + +#endif diff --git a/src/util/irep_ids.txt b/src/util/irep_ids.txt index 5e364d97ea0..a9672b2cec7 100644 --- a/src/util/irep_ids.txt +++ b/src/util/irep_ids.txt @@ -804,4 +804,5 @@ cprover_string_to_lower_case_func cprover_string_to_upper_case_func cprover_string_trim_func cprover_string_value_of_func -basic_block_covered_lines \ No newline at end of file +basic_block_covered_lines +is_nondet_nullable diff --git a/src/util/std_code.h b/src/util/std_code.h index 17d038274a3..85a35252dfb 100644 --- a/src/util/std_code.h +++ b/src/util/std_code.h @@ -1036,14 +1036,41 @@ class side_effect_expr_nondett:public side_effect_exprt public: side_effect_expr_nondett():side_effect_exprt(ID_nondet) { + set_nullable(true); } explicit side_effect_expr_nondett(const typet &_type): side_effect_exprt(ID_nondet, _type) { + set_nullable(true); + } + + void set_nullable(bool nullable) + { + set(ID_is_nondet_nullable, nullable); + } + + bool get_nullable() const + { + return get_bool(ID_is_nondet_nullable); } }; +inline side_effect_expr_nondett &to_side_effect_expr_nondet(exprt &expr) +{ + auto &side_effect_expr_nondet=to_side_effect_expr(expr); + assert(side_effect_expr_nondet.get_statement()==ID_nondet); + return static_cast(side_effect_expr_nondet); +} + +inline const side_effect_expr_nondett &to_side_effect_expr_nondet( + const exprt &expr) +{ + const auto &side_effect_expr_nondet=to_side_effect_expr(expr); + assert(side_effect_expr_nondet.get_statement()==ID_nondet); + return static_cast(side_effect_expr_nondet); +} + /*! \brief A function call side effect */ class side_effect_expr_function_callt:public side_effect_exprt From ff72ddc8c5693331cf2c6141193aaf614dc6f08a Mon Sep 17 00:00:00 2001 From: reuk Date: Tue, 18 Apr 2017 16:18:09 +0100 Subject: [PATCH 200/699] Ensure assume only throws upon predicate failure --- src/java_bytecode/library/src/org/cprover/CProver.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/java_bytecode/library/src/org/cprover/CProver.java b/src/java_bytecode/library/src/org/cprover/CProver.java index 0dcae58c67e..6aadd228e9e 100644 --- a/src/java_bytecode/library/src/org/cprover/CProver.java +++ b/src/java_bytecode/library/src/org/cprover/CProver.java @@ -117,10 +117,9 @@ public static T nondetWithoutNull() public static void assume(boolean condition) { - if(enableAssume) + if(enableAssume && !condition) { - throw new RuntimeException( - "Cannot execute program with CProver.assume()"); + throw new RuntimeException("CProver.assume() predicate is false"); } } } From 520cf38ce751913d48b7a8f0a01b509590bcc105 Mon Sep 17 00:00:00 2001 From: Cristina Date: Thu, 20 Apr 2017 16:33:32 +0100 Subject: [PATCH 201/699] Handle typecast when evaluating addresses in the interpreter --- src/goto-programs/interpreter_evaluate.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/goto-programs/interpreter_evaluate.cpp b/src/goto-programs/interpreter_evaluate.cpp index f285328aedd..b711be84ba2 100644 --- a/src/goto-programs/interpreter_evaluate.cpp +++ b/src/goto-programs/interpreter_evaluate.cpp @@ -1256,6 +1256,15 @@ mp_integer interpretert::evaluate_address( if(result.size()==1) return result[0]; } + else if(expr.id()==ID_typecast) + { + if(expr.operands().size()!=1) + throw "typecast expects one operand"; + + assert(expr.type().id()==ID_pointer); + + return evaluate_address(expr.op0(), fail_quietly); + } if(!fail_quietly) { error() << "!! failed to evaluate address: " From b8586a6e3327cff94bc43cb6ef21ada8128eb556 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 21 Apr 2017 15:30:08 +0100 Subject: [PATCH 202/699] Move coverage arg-parsing into cover.cpp This unifies test-generator's version of coverage instrumentation with cbmc's base version, which should make future changes to the two easier to keep in sync. An upcoming changeset will update the test-generator tool to use this. --- src/goto-instrument/cover.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/goto-instrument/cover.cpp b/src/goto-instrument/cover.cpp index f84fe3d5f3d..33ce83bc2f7 100644 --- a/src/goto-instrument/cover.cpp +++ b/src/goto-instrument/cover.cpp @@ -1769,10 +1769,33 @@ bool instrument_cover_goals( } } + // check existing test goals + coverage_goalst existing_goals; + if(cmdline.isset("existing-coverage")) + { + msg.status() << "Check existing coverage goals" << messaget::eom; + // get file with covered test goals + const std::string coverage=cmdline.get_value("existing-coverage"); + // get a coverage_goalst object + if(coverage_goalst::get_coverage_goals(coverage, msgh, existing_goals)) + { + msg.error() << "get_coverage_goals failed" << messaget::eom; + return true; + } + } + msg.status() << "Instrumenting coverage goals" << messaget::eom; for(const auto &criterion : criteria) - instrument_cover_goals(symbol_table, goto_functions, criterion); + { + instrument_cover_goals( + symbol_table, + goto_functions, + criterion, + existing_goals, + cmdline.isset("cover-function-only"), + cmdline.isset("no-trivial-tests")); + } goto_functions.update(); return false; From c195e63c34dcc4cadb4c92fa19cee842b6a82060 Mon Sep 17 00:00:00 2001 From: reuk Date: Mon, 24 Apr 2017 11:40:33 +0100 Subject: [PATCH 203/699] Remove 'erase' in replace_java_nondet.cpp Erasing a range of instructions from a goto program can cause memory bugs when `goto_program::update` is called. Specifically, if any of the remaining nodes in the program have elements of `targets` which point into the erased range, then the program may attempt an invalid read during the `update` call. To avoid this, I thought of two options: - check through the goto-program for instructions with `target`s that point into the removed range, and remove those `target`s, or - just replace the existing instructions with no-ops. Although I think the first solution is better, I can't think of a good way of doing it with acceptable complexity, so this patch implements the second option. --- src/goto-programs/replace_java_nondet.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/goto-programs/replace_java_nondet.cpp b/src/goto-programs/replace_java_nondet.cpp index b78a0819cac..1faddf24491 100644 --- a/src/goto-programs/replace_java_nondet.cpp +++ b/src/goto-programs/replace_java_nondet.cpp @@ -215,9 +215,9 @@ Function: check_and_replace_target \*******************************************************************/ -static goto_programt::const_targett check_and_replace_target( +static goto_programt::targett check_and_replace_target( goto_programt &goto_program, - const goto_programt::const_targett &target) + const goto_programt::targett &target) { // Check whether this is a nondet library method, and return if not const auto instr_info=get_nondet_instruction_info(target); @@ -241,7 +241,7 @@ static goto_programt::const_targett check_and_replace_target( to_symbol_expr(next_instr_assign_lhs).get_identifier(); auto &instructions=goto_program.instructions; - const auto end=instructions.cend(); + const auto end=instructions.end(); // Look for an instruction where this name is on the RHS of an assignment const auto matching_assignment=std::find_if( @@ -263,10 +263,15 @@ static goto_programt::const_targett check_and_replace_target( const auto after_matching_assignment=std::next(matching_assignment); assert(after_matching_assignment!=end); - const auto after_erased=goto_program.instructions.erase( - target, after_matching_assignment); + std::for_each( + target, + after_matching_assignment, + [](goto_programt::instructiont &instr) + { + instr.make_skip(); + }); - const auto inserted=goto_program.insert_before(after_erased); + const auto inserted=goto_program.insert_before(after_matching_assignment); inserted->make_assignment(); side_effect_expr_nondett inserted_expr(nondet_var.type()); inserted_expr.set_nullable( @@ -278,7 +283,7 @@ static goto_programt::const_targett check_and_replace_target( goto_program.update(); - return after_erased; + return after_matching_assignment; } /*******************************************************************\ @@ -297,8 +302,8 @@ Function: replace_java_nondet static void replace_java_nondet(goto_programt &goto_program) { - for(auto instruction_iterator=goto_program.instructions.cbegin(), - end=goto_program.instructions.cend(); + for(auto instruction_iterator=goto_program.instructions.begin(), + end=goto_program.instructions.end(); instruction_iterator!=end;) { instruction_iterator=check_and_replace_target( From 8ad72a70de790c8e1c21a1c7df3484c6b7e6daba Mon Sep 17 00:00:00 2001 From: reuk Date: Tue, 25 Apr 2017 09:38:20 +0100 Subject: [PATCH 204/699] Fix linter complaint --- src/cegis/cegis-util/type_helper.cpp | 62 ++++++++++++++++++---------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/src/cegis/cegis-util/type_helper.cpp b/src/cegis/cegis-util/type_helper.cpp index 68e4dc8439d..a4ea0e84cf1 100644 --- a/src/cegis/cegis-util/type_helper.cpp +++ b/src/cegis/cegis-util/type_helper.cpp @@ -16,12 +16,16 @@ Author: Daniel Kroening, kroening@kroening.com #include -const typet &replace_struct_by_symbol_type(const symbol_tablet &st, - const typet &type) +const typet &replace_struct_by_symbol_type( + const symbol_tablet &st, + const typet &type) { const irep_idt &type_id=type.id(); - if(ID_struct != type_id && ID_incomplete_struct != type_id - && ID_union != type_id && ID_incomplete_union != type_id) return type; + if(type_id!=ID_struct && type_id!=ID_incomplete_struct && + type_id!=ID_union && type_id!=ID_incomplete_union) + { + return type; + } std::string tag(TAG_PREFIX); tag+=id2string(to_struct_union_type(type).get_tag()); return st.lookup(tag).type; @@ -31,16 +35,20 @@ namespace { bool instanceof(const typet &lhs, const typet &rhs, const namespacet &ns) { - if(type_eq(lhs, rhs, ns)) return true; - assert(ID_class == lhs.id()); - const class_typet &lhs_class=to_class_type(lhs); - const class_typet::basest &bases=lhs_class.bases(); - for(const exprt &base : bases) + if(type_eq(lhs, rhs, ns)) { - const typet &type=base.type(); - if (instanceof(ns.follow(type), rhs, ns)) return true; + return true; } - return false; + assert(ID_class==lhs.id()); + const class_typet &lhs_class=to_class_type(lhs); + const class_typet::basest &bases=lhs_class.bases(); + return std::any_of( + std::begin(bases), + std::end(bases), + [&](const exprt &base) + { + return instanceof(ns.follow(base.type()), rhs, ns); + }); } } @@ -49,22 +57,32 @@ bool instanceof(const symbol_tablet &st, const typet &lhs, const typet &rhs) const namespacet ns(st); const typet &resolved_lhs=ns.follow(lhs); const typet &resolved_rhs=ns.follow(rhs); - if(ID_class != resolved_lhs.id() || ID_class != resolved_rhs.id()) + if(ID_class!=resolved_lhs.id() || ID_class!=resolved_rhs.id()) + { return type_eq(resolved_lhs, resolved_rhs, ns); + } return instanceof(resolved_lhs, resolved_rhs, ns); } -instanceof_anyt::instanceof_anyt(const symbol_tablet &st, - const std::set &types) : - st(st), types(types) +instanceof_anyt::instanceof_anyt( + const symbol_tablet &st, + const std::set &types): + st(st), + types(types) { } -bool instanceof_anyt::operator ()(const typet &type) const +bool instanceof_anyt::operator()(const typet &type) const { - if(types.empty()) return true; - return types.end() - != std::find_if(types.begin(), types.end(), - [this, &type](const typet &rhs) - { return instanceof(st, type, rhs);}); + if(types.empty()) + { + return true; + } + return types.end()!=std::find_if( + types.begin(), + types.end(), + [this, &type](const typet &rhs) + { + return instanceof(st, type, rhs); + }); } From 6deaa3b899df6f64088bcc789c5fdb19ece07b01 Mon Sep 17 00:00:00 2001 From: reuk Date: Thu, 27 Apr 2017 10:27:37 +0100 Subject: [PATCH 205/699] Remove skip in replace_java_nondet.cpp The changes in replace_java_nondet uncovered a similar 'erase' issue in convert_nondet, which this patch also fixes. --- src/goto-programs/convert_nondet.cpp | 17 ++++++++++------- src/goto-programs/replace_java_nondet.cpp | 4 ++++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/goto-programs/convert_nondet.cpp b/src/goto-programs/convert_nondet.cpp index 9e54d70d893..55c52fe8f4b 100644 --- a/src/goto-programs/convert_nondet.cpp +++ b/src/goto-programs/convert_nondet.cpp @@ -9,6 +9,7 @@ Author: Reuben Thomas, reuben.thomas@diffblue.com #include "goto-programs/convert_nondet.h" #include "goto-programs/goto_convert.h" #include "goto-programs/goto_model.h" +#include "goto-programs/remove_skip.h" #include "java_bytecode/java_object_factory.h" // gen_nondet_init @@ -34,9 +35,9 @@ Function: insert_nondet_init_code \*******************************************************************/ -static goto_programt::const_targett insert_nondet_init_code( +static goto_programt::targett insert_nondet_init_code( goto_programt &goto_program, - const goto_programt::const_targett &target, + const goto_programt::targett &target, symbol_tablet &symbol_table, message_handlert &message_handler, size_t max_nondet_array_length) @@ -82,7 +83,7 @@ static goto_programt::const_targett insert_nondet_init_code( const auto source_loc=target->source_location; // Erase the nondet assignment - const auto after_erased=goto_program.instructions.erase(target); + target->make_skip(); // Generate nondet init code code_blockt init_code; @@ -101,10 +102,10 @@ static goto_programt::const_targett insert_nondet_init_code( goto_convert(init_code, symbol_table, new_instructions, message_handler); // Insert the new instructions into the instruction list - goto_program.destructive_insert(after_erased, new_instructions); + goto_program.destructive_insert(next_instr, new_instructions); goto_program.update(); - return after_erased; + return next_instr; } /*******************************************************************\ @@ -129,8 +130,8 @@ static void convert_nondet( message_handlert &message_handler, size_t max_nondet_array_length) { - for(auto instruction_iterator=goto_program.instructions.cbegin(), - end=goto_program.instructions.cend(); + for(auto instruction_iterator=goto_program.instructions.begin(), + end=goto_program.instructions.end(); instruction_iterator!=end;) { instruction_iterator=insert_nondet_init_code( @@ -160,4 +161,6 @@ void convert_nondet( } goto_functions.compute_location_numbers(); + + remove_skip(goto_functions); } diff --git a/src/goto-programs/replace_java_nondet.cpp b/src/goto-programs/replace_java_nondet.cpp index 1faddf24491..b0514d60a7b 100644 --- a/src/goto-programs/replace_java_nondet.cpp +++ b/src/goto-programs/replace_java_nondet.cpp @@ -9,6 +9,7 @@ Author: Reuben Thomas, reuben.thomas@diffblue.com #include "goto-programs/replace_java_nondet.h" #include "goto-programs/goto_convert.h" #include "goto-programs/goto_model.h" +#include "goto-programs/remove_skip.h" #include "util/irep_ids.h" @@ -320,5 +321,8 @@ void replace_java_nondet(goto_functionst &goto_functions) { replace_java_nondet(goto_program.second.body); } + goto_functions.compute_location_numbers(); + + remove_skip(goto_functions); } From d15d84238d4977bcad5995713acda18a90ba5113 Mon Sep 17 00:00:00 2001 From: reuk Date: Thu, 27 Apr 2017 10:39:23 +0100 Subject: [PATCH 206/699] Fix indentation in convert_nondet --- src/goto-programs/convert_nondet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/goto-programs/convert_nondet.cpp b/src/goto-programs/convert_nondet.cpp index 55c52fe8f4b..e4655716d9b 100644 --- a/src/goto-programs/convert_nondet.cpp +++ b/src/goto-programs/convert_nondet.cpp @@ -132,7 +132,7 @@ static void convert_nondet( { for(auto instruction_iterator=goto_program.instructions.begin(), end=goto_program.instructions.end(); - instruction_iterator!=end;) + instruction_iterator!=end;) { instruction_iterator=insert_nondet_init_code( goto_program, From 1e9123f0ac7b56378fb8485d50a2f6be2a4cae30 Mon Sep 17 00:00:00 2001 From: Cristina Date: Fri, 21 Apr 2017 14:34:26 +0100 Subject: [PATCH 207/699] Always initialise the exceptional return variable of the entry function --- src/goto-programs/remove_exceptions.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/goto-programs/remove_exceptions.cpp b/src/goto-programs/remove_exceptions.cpp index 5058164147c..5726831804f 100644 --- a/src/goto-programs/remove_exceptions.cpp +++ b/src/goto-programs/remove_exceptions.cpp @@ -90,6 +90,26 @@ void remove_exceptionst::add_exceptional_returns( if(goto_program.empty()) return; + // the entry function has already been added to the symbol table + // if you find it, initialise it + if(symbol_table.has_symbol(id2string(function_id)+EXC_SUFFIX)) + { + const symbolt &symbol= + symbol_table.lookup(id2string(function_id)+EXC_SUFFIX); + symbol_exprt lhs_expr_null=symbol.symbol_expr(); + null_pointer_exprt rhs_expr_null((pointer_typet(empty_typet()))); + goto_programt::targett t_null= + goto_program.insert_before(goto_program.instructions.begin()); + t_null->make_assignment(); + t_null->source_location= + goto_program.instructions.begin()->source_location; + t_null->code=code_assignt( + lhs_expr_null, + rhs_expr_null); + t_null->function=function_id; + return; + } + // We generate an exceptional return value for any function that has // a throw or a function call. This can be improved by only considering // function calls that may escape exceptions. However, this will From 6d1feea66f519254515ade1c2b6fbce31a4af4d5 Mon Sep 17 00:00:00 2001 From: Cristina Date: Thu, 20 Apr 2017 11:00:46 +0100 Subject: [PATCH 208/699] Set the bytecode index for the instrumentation in goto_check.cpp --- src/analyses/goto_check.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/analyses/goto_check.cpp b/src/analyses/goto_check.cpp index cc418d6aed9..635e0eb8f9a 100644 --- a/src/analyses/goto_check.cpp +++ b/src/analyses/goto_check.cpp @@ -1820,6 +1820,11 @@ void goto_checkt::goto_check( if(it->source_location.get_column()!=irep_idt()) i_it->source_location.set_column(it->source_location.get_column()); + + if(mode==ID_java && + it->source_location.get_java_bytecode_index()!=irep_idt()) + i_it->source_location.set_java_bytecode_index( + it->source_location.get_java_bytecode_index()); } if(i_it->function==irep_idt()) From 67961355a52e7193dcf99611884b5dcb8d5038ae Mon Sep 17 00:00:00 2001 From: Cristina Date: Thu, 20 Apr 2017 13:44:58 +0100 Subject: [PATCH 209/699] Added the bytecode index to the expected result of the regression tests --- regression/cbmc-java/NullPointer1/test.desc | 2 +- regression/cbmc-java/NullPointer4/test.desc | 2 +- src/analyses/goto_check.cpp | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/regression/cbmc-java/NullPointer1/test.desc b/regression/cbmc-java/NullPointer1/test.desc index d479356875a..b11a57a56fd 100644 --- a/regression/cbmc-java/NullPointer1/test.desc +++ b/regression/cbmc-java/NullPointer1/test.desc @@ -3,7 +3,7 @@ NullPointer1.class --pointer-check --stop-on-fail ^EXIT=10$ ^SIGNAL=0$ -^ file NullPointer1.java line 16 function java::NullPointer1.main:\(\[Ljava/lang/String;\)V$ +^ file NullPointer1.java line 16 function java::NullPointer1.main:\(\[Ljava/lang/String;\)V bytecode_index 9$ ^VERIFICATION FAILED$ -- ^warning: ignoring diff --git a/regression/cbmc-java/NullPointer4/test.desc b/regression/cbmc-java/NullPointer4/test.desc index 2e1b728c1fc..28c9e6f47fd 100644 --- a/regression/cbmc-java/NullPointer4/test.desc +++ b/regression/cbmc-java/NullPointer4/test.desc @@ -3,7 +3,7 @@ NullPointer4.class --pointer-check --stop-on-fail ^EXIT=10$ ^SIGNAL=0$ -^ file NullPointer4.java line 6 function java::NullPointer4.main:\(\[Ljava/lang/String;\)V$ +^ file NullPointer4.java line 6 function java::NullPointer4.main:\(\[Ljava/lang/String;\)V bytecode_index 4$ ^VERIFICATION FAILED$ -- ^warning: ignoring diff --git a/src/analyses/goto_check.cpp b/src/analyses/goto_check.cpp index 635e0eb8f9a..a6871b94d23 100644 --- a/src/analyses/goto_check.cpp +++ b/src/analyses/goto_check.cpp @@ -1821,8 +1821,7 @@ void goto_checkt::goto_check( if(it->source_location.get_column()!=irep_idt()) i_it->source_location.set_column(it->source_location.get_column()); - if(mode==ID_java && - it->source_location.get_java_bytecode_index()!=irep_idt()) + if(it->source_location.get_java_bytecode_index()!=irep_idt()) i_it->source_location.set_java_bytecode_index( it->source_location.get_java_bytecode_index()); } From 21eeb297950fc06e830c293e015e0302fa590bbe Mon Sep 17 00:00:00 2001 From: Joel Allred Date: Thu, 20 Apr 2017 09:46:20 +0100 Subject: [PATCH 210/699] Enable working smoke tests Set the currently working some tests as CORE and link the others to GitHub issues. --- regression/strings-smoke-tests/java_append_char/test.desc | 2 +- regression/strings-smoke-tests/java_append_int/test.desc | 2 +- regression/strings-smoke-tests/java_append_object/test.desc | 1 + regression/strings-smoke-tests/java_append_string/test.desc | 2 +- regression/strings-smoke-tests/java_case/test.desc | 2 +- regression/strings-smoke-tests/java_char_array/test.desc | 2 +- regression/strings-smoke-tests/java_char_array_init/test.desc | 1 + regression/strings-smoke-tests/java_char_at/test.desc | 2 +- regression/strings-smoke-tests/java_code_point/test.desc | 2 +- regression/strings-smoke-tests/java_compare/test.desc | 2 +- regression/strings-smoke-tests/java_concat/test.desc | 2 +- regression/strings-smoke-tests/java_contains/test.desc | 3 ++- regression/strings-smoke-tests/java_delete/test.desc | 2 +- regression/strings-smoke-tests/java_delete_char_at/test.desc | 2 +- regression/strings-smoke-tests/java_empty/test.desc | 2 +- regression/strings-smoke-tests/java_endswith/test.desc | 2 +- regression/strings-smoke-tests/java_equal/test.desc | 4 ++-- regression/strings-smoke-tests/java_float/test.desc | 2 +- regression/strings-smoke-tests/java_hash_code/test.desc | 2 +- regression/strings-smoke-tests/java_index_of/test.desc | 3 ++- regression/strings-smoke-tests/java_index_of_char/test.desc | 3 ++- regression/strings-smoke-tests/java_insert_char/test.desc | 2 +- .../strings-smoke-tests/java_insert_char_array/test.desc | 2 +- regression/strings-smoke-tests/java_insert_int/test.desc | 2 +- regression/strings-smoke-tests/java_insert_multiple/test.desc | 2 +- regression/strings-smoke-tests/java_insert_string/test.desc | 2 +- regression/strings-smoke-tests/java_int_to_string/test.desc | 2 +- regression/strings-smoke-tests/java_intern/test.desc | 2 +- regression/strings-smoke-tests/java_last_index_of/test.desc | 3 ++- .../strings-smoke-tests/java_last_index_of_char/test.desc | 2 +- regression/strings-smoke-tests/java_length/test.desc | 2 +- regression/strings-smoke-tests/java_parseint/test.desc | 2 +- regression/strings-smoke-tests/java_replace/test.desc | 3 ++- regression/strings-smoke-tests/java_replace_char/test.desc | 2 +- regression/strings-smoke-tests/java_set_char_at/test.desc | 2 +- regression/strings-smoke-tests/java_set_length/test.desc | 4 ++-- regression/strings-smoke-tests/java_starts_with/test.desc | 2 +- .../strings-smoke-tests/java_string_builder_length/test.desc | 2 +- regression/strings-smoke-tests/java_subsequence/test.desc | 2 +- regression/strings-smoke-tests/java_substring/test.desc | 2 +- regression/strings-smoke-tests/java_trim/test.desc | 4 ++-- 41 files changed, 49 insertions(+), 42 deletions(-) diff --git a/regression/strings-smoke-tests/java_append_char/test.desc b/regression/strings-smoke-tests/java_append_char/test.desc index 0f1b3ae243f..88d1cbf2114 100644 --- a/regression/strings-smoke-tests/java_append_char/test.desc +++ b/regression/strings-smoke-tests/java_append_char/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_append_char.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_append_int/test.desc b/regression/strings-smoke-tests/java_append_int/test.desc index e1455859470..e0b30e7827d 100644 --- a/regression/strings-smoke-tests/java_append_int/test.desc +++ b/regression/strings-smoke-tests/java_append_int/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_append_int.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_append_object/test.desc b/regression/strings-smoke-tests/java_append_object/test.desc index 5db2ac1db73..787852963ed 100644 --- a/regression/strings-smoke-tests/java_append_object/test.desc +++ b/regression/strings-smoke-tests/java_append_object/test.desc @@ -5,3 +5,4 @@ test_append_object.class ^SIGNAL=0$ ^VERIFICATION SUCCESSFUL$ -- +Issue: diffblue/test-gen#82 diff --git a/regression/strings-smoke-tests/java_append_string/test.desc b/regression/strings-smoke-tests/java_append_string/test.desc index 18035539d58..943ca820bcc 100644 --- a/regression/strings-smoke-tests/java_append_string/test.desc +++ b/regression/strings-smoke-tests/java_append_string/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_append_string.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_case/test.desc b/regression/strings-smoke-tests/java_case/test.desc index e01a5054419..9a254ae3484 100644 --- a/regression/strings-smoke-tests/java_case/test.desc +++ b/regression/strings-smoke-tests/java_case/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_case.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_char_array/test.desc b/regression/strings-smoke-tests/java_char_array/test.desc index ecce56c1ab8..efb6ad4c5d7 100644 --- a/regression/strings-smoke-tests/java_char_array/test.desc +++ b/regression/strings-smoke-tests/java_char_array/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_char_array.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_char_array_init/test.desc b/regression/strings-smoke-tests/java_char_array_init/test.desc index fc1cde2392c..04096a8a984 100644 --- a/regression/strings-smoke-tests/java_char_array_init/test.desc +++ b/regression/strings-smoke-tests/java_char_array_init/test.desc @@ -5,3 +5,4 @@ test_init.class ^SIGNAL=0$ ^VERIFICATION SUCCESSFUL$ -- +cbmc/test-gen#259 diff --git a/regression/strings-smoke-tests/java_char_at/test.desc b/regression/strings-smoke-tests/java_char_at/test.desc index 5bf29fc7a4d..f2d5ecad6c7 100644 --- a/regression/strings-smoke-tests/java_char_at/test.desc +++ b/regression/strings-smoke-tests/java_char_at/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_char_at.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_code_point/test.desc b/regression/strings-smoke-tests/java_code_point/test.desc index 012c7c3501b..e3be9616fa5 100644 --- a/regression/strings-smoke-tests/java_code_point/test.desc +++ b/regression/strings-smoke-tests/java_code_point/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_code_point.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_compare/test.desc b/regression/strings-smoke-tests/java_compare/test.desc index 38aa025f416..9e6810476b9 100644 --- a/regression/strings-smoke-tests/java_compare/test.desc +++ b/regression/strings-smoke-tests/java_compare/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_compare.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_concat/test.desc b/regression/strings-smoke-tests/java_concat/test.desc index fb784efd723..2dcca464779 100644 --- a/regression/strings-smoke-tests/java_concat/test.desc +++ b/regression/strings-smoke-tests/java_concat/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_concat.class --refine-strings ^EXIT=10$ diff --git a/regression/strings-smoke-tests/java_contains/test.desc b/regression/strings-smoke-tests/java_contains/test.desc index 2b96346d718..e40d51aa473 100644 --- a/regression/strings-smoke-tests/java_contains/test.desc +++ b/regression/strings-smoke-tests/java_contains/test.desc @@ -1,4 +1,4 @@ -FUTURE +KNOWNBUG test_contains.class --refine-strings ^EXIT=10$ @@ -6,3 +6,4 @@ test_contains.class ^\[.*assertion.1\].* line 8.* SUCCESS$ ^\[.*assertion.2\].* line 9.* FAILURE$ -- +Issue: diffblue/test-gen#201 diff --git a/regression/strings-smoke-tests/java_delete/test.desc b/regression/strings-smoke-tests/java_delete/test.desc index 27a1406cdb7..f0c0aedda91 100644 --- a/regression/strings-smoke-tests/java_delete/test.desc +++ b/regression/strings-smoke-tests/java_delete/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_delete.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_delete_char_at/test.desc b/regression/strings-smoke-tests/java_delete_char_at/test.desc index 94ba56a2c54..d415d16e9b6 100644 --- a/regression/strings-smoke-tests/java_delete_char_at/test.desc +++ b/regression/strings-smoke-tests/java_delete_char_at/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_delete_char_at.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_empty/test.desc b/regression/strings-smoke-tests/java_empty/test.desc index 9951c8a13ee..181ff4ee5fd 100644 --- a/regression/strings-smoke-tests/java_empty/test.desc +++ b/regression/strings-smoke-tests/java_empty/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_empty.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_endswith/test.desc b/regression/strings-smoke-tests/java_endswith/test.desc index 0461a3e50e6..8b058f48d78 100644 --- a/regression/strings-smoke-tests/java_endswith/test.desc +++ b/regression/strings-smoke-tests/java_endswith/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_endswith.class --refine-strings ^EXIT=10$ diff --git a/regression/strings-smoke-tests/java_equal/test.desc b/regression/strings-smoke-tests/java_equal/test.desc index 05f0f383230..964c3b72bae 100644 --- a/regression/strings-smoke-tests/java_equal/test.desc +++ b/regression/strings-smoke-tests/java_equal/test.desc @@ -1,6 +1,6 @@ -FUTURE +CORE test_equal.class ---refine-strings +--refine-strings --string-max-length 100 --string-max-length 100 ^EXIT=10$ ^SIGNAL=0$ ^\[.*assertion.1\].* line 8.* FAILURE$ diff --git a/regression/strings-smoke-tests/java_float/test.desc b/regression/strings-smoke-tests/java_float/test.desc index 427d1fca836..e81b6b4feba 100644 --- a/regression/strings-smoke-tests/java_float/test.desc +++ b/regression/strings-smoke-tests/java_float/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_float.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_hash_code/test.desc b/regression/strings-smoke-tests/java_hash_code/test.desc index 2db8d7116f9..fc628393186 100644 --- a/regression/strings-smoke-tests/java_hash_code/test.desc +++ b/regression/strings-smoke-tests/java_hash_code/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_hash_code.class --refine-strings ^EXIT=10$ diff --git a/regression/strings-smoke-tests/java_index_of/test.desc b/regression/strings-smoke-tests/java_index_of/test.desc index f2fa825597d..6033af25d1b 100644 --- a/regression/strings-smoke-tests/java_index_of/test.desc +++ b/regression/strings-smoke-tests/java_index_of/test.desc @@ -1,7 +1,8 @@ -FUTURE +KNOWNBUG test_index_of.class --refine-strings ^EXIT=0$ ^SIGNAL=0$ ^VERIFICATION SUCCESSFUL$ -- +Issue: cbmc/test-gen#77 diff --git a/regression/strings-smoke-tests/java_index_of_char/test.desc b/regression/strings-smoke-tests/java_index_of_char/test.desc index 63382a455f3..a95467b52e4 100644 --- a/regression/strings-smoke-tests/java_index_of_char/test.desc +++ b/regression/strings-smoke-tests/java_index_of_char/test.desc @@ -1,7 +1,8 @@ -FUTURE +CORE test_index_of_char.class --refine-strings ^EXIT=0$ ^SIGNAL=0$ ^VERIFICATION SUCCESSFUL$ -- +Issue: cbmc/test-gen#77 diff --git a/regression/strings-smoke-tests/java_insert_char/test.desc b/regression/strings-smoke-tests/java_insert_char/test.desc index 77d3ce2ebd9..0e9a06d5afb 100644 --- a/regression/strings-smoke-tests/java_insert_char/test.desc +++ b/regression/strings-smoke-tests/java_insert_char/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_insert_char.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_insert_char_array/test.desc b/regression/strings-smoke-tests/java_insert_char_array/test.desc index d48c601b61b..082771dd2db 100644 --- a/regression/strings-smoke-tests/java_insert_char_array/test.desc +++ b/regression/strings-smoke-tests/java_insert_char_array/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_insert_char_array.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_insert_int/test.desc b/regression/strings-smoke-tests/java_insert_int/test.desc index dc039fedbea..df87a5f5728 100644 --- a/regression/strings-smoke-tests/java_insert_int/test.desc +++ b/regression/strings-smoke-tests/java_insert_int/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_insert_int.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_insert_multiple/test.desc b/regression/strings-smoke-tests/java_insert_multiple/test.desc index 983d416dd3b..bb9a23f1b5c 100644 --- a/regression/strings-smoke-tests/java_insert_multiple/test.desc +++ b/regression/strings-smoke-tests/java_insert_multiple/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_insert_multiple.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_insert_string/test.desc b/regression/strings-smoke-tests/java_insert_string/test.desc index b438d32d6d9..44bf9f268d9 100644 --- a/regression/strings-smoke-tests/java_insert_string/test.desc +++ b/regression/strings-smoke-tests/java_insert_string/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_insert_string.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_int_to_string/test.desc b/regression/strings-smoke-tests/java_int_to_string/test.desc index a615a10f538..38fa5289bd2 100644 --- a/regression/strings-smoke-tests/java_int_to_string/test.desc +++ b/regression/strings-smoke-tests/java_int_to_string/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_int.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_intern/test.desc b/regression/strings-smoke-tests/java_intern/test.desc index 645e267029c..c8d0eea43bd 100644 --- a/regression/strings-smoke-tests/java_intern/test.desc +++ b/regression/strings-smoke-tests/java_intern/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_intern.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_last_index_of/test.desc b/regression/strings-smoke-tests/java_last_index_of/test.desc index 77bc5b7f18f..5ee1604e846 100644 --- a/regression/strings-smoke-tests/java_last_index_of/test.desc +++ b/regression/strings-smoke-tests/java_last_index_of/test.desc @@ -1,7 +1,8 @@ -FUTURE +KNOWNBUG test_last_index_of.class --refine-strings ^EXIT=0$ ^SIGNAL=0$ ^VERIFICATION SUCCESSFUL$ -- +Issue: diffblue/test-gen#77 diff --git a/regression/strings-smoke-tests/java_last_index_of_char/test.desc b/regression/strings-smoke-tests/java_last_index_of_char/test.desc index 3e9a3d4b547..aa88fc5f6ef 100644 --- a/regression/strings-smoke-tests/java_last_index_of_char/test.desc +++ b/regression/strings-smoke-tests/java_last_index_of_char/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_last_index_of_char.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_length/test.desc b/regression/strings-smoke-tests/java_length/test.desc index 913afbf13c7..d7f0e02feca 100644 --- a/regression/strings-smoke-tests/java_length/test.desc +++ b/regression/strings-smoke-tests/java_length/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_length.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_parseint/test.desc b/regression/strings-smoke-tests/java_parseint/test.desc index 9cb70f5a957..6a513e61deb 100644 --- a/regression/strings-smoke-tests/java_parseint/test.desc +++ b/regression/strings-smoke-tests/java_parseint/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_parseint.class --refine-strings ^EXIT=10$ diff --git a/regression/strings-smoke-tests/java_replace/test.desc b/regression/strings-smoke-tests/java_replace/test.desc index 59c7d326a0b..d86aae6b5a9 100644 --- a/regression/strings-smoke-tests/java_replace/test.desc +++ b/regression/strings-smoke-tests/java_replace/test.desc @@ -1,7 +1,8 @@ FUTURE test_replace.class ---refine-strings +--refine-strings --string-max-length 100 ^EXIT=0$ ^SIGNAL=0$ ^VERIFICATION SUCCESSFUL$ -- +diffblue/test-gen#256 diff --git a/regression/strings-smoke-tests/java_replace_char/test.desc b/regression/strings-smoke-tests/java_replace_char/test.desc index 528d4eead6c..5c336326e5d 100644 --- a/regression/strings-smoke-tests/java_replace_char/test.desc +++ b/regression/strings-smoke-tests/java_replace_char/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_replace_char.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_set_char_at/test.desc b/regression/strings-smoke-tests/java_set_char_at/test.desc index 650e7712278..1c471d0194a 100644 --- a/regression/strings-smoke-tests/java_set_char_at/test.desc +++ b/regression/strings-smoke-tests/java_set_char_at/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_set_char_at.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_set_length/test.desc b/regression/strings-smoke-tests/java_set_length/test.desc index ab59e459eb1..d19eb265fa4 100644 --- a/regression/strings-smoke-tests/java_set_length/test.desc +++ b/regression/strings-smoke-tests/java_set_length/test.desc @@ -1,6 +1,6 @@ -FUTURE +CORE test_set_length.class ---refine-strings +--refine-strings --string-max-length 100 ^EXIT=10$ ^SIGNAL=0$ ^\[.*assertion.1\].* line 8.* SUCCESS$ diff --git a/regression/strings-smoke-tests/java_starts_with/test.desc b/regression/strings-smoke-tests/java_starts_with/test.desc index 5c5d85565c2..ec6b84102f2 100644 --- a/regression/strings-smoke-tests/java_starts_with/test.desc +++ b/regression/strings-smoke-tests/java_starts_with/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_starts_with.class --refine-strings ^EXIT=10$ diff --git a/regression/strings-smoke-tests/java_string_builder_length/test.desc b/regression/strings-smoke-tests/java_string_builder_length/test.desc index ba9187109ed..2a37e02a36c 100644 --- a/regression/strings-smoke-tests/java_string_builder_length/test.desc +++ b/regression/strings-smoke-tests/java_string_builder_length/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_sb_length.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_subsequence/test.desc b/regression/strings-smoke-tests/java_subsequence/test.desc index 34585a7900d..df3cc28619f 100644 --- a/regression/strings-smoke-tests/java_subsequence/test.desc +++ b/regression/strings-smoke-tests/java_subsequence/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_subsequence.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_substring/test.desc b/regression/strings-smoke-tests/java_substring/test.desc index 8a29460f529..26ec800cfac 100644 --- a/regression/strings-smoke-tests/java_substring/test.desc +++ b/regression/strings-smoke-tests/java_substring/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE test_substring.class --refine-strings ^EXIT=0$ diff --git a/regression/strings-smoke-tests/java_trim/test.desc b/regression/strings-smoke-tests/java_trim/test.desc index c7a307c37ed..171ada28356 100644 --- a/regression/strings-smoke-tests/java_trim/test.desc +++ b/regression/strings-smoke-tests/java_trim/test.desc @@ -1,6 +1,6 @@ -FUTURE +CORE test_trim.class ---refine-strings +--refine-strings --string-max-length 100 ^EXIT=10$ ^SIGNAL=0$ ^\[.*assertion.1\].* line 6.* SUCCESS$ From 95844654fcfb0e7754a77e789eeb4ef9b9780fff Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Thu, 13 Apr 2017 15:55:07 +0100 Subject: [PATCH 211/699] Correction in add_axioms_for_set_length This corrects issue diffblue/test-gen#244 There was a an error in add_axioms_for_set_length: |s1| was compared to idx instead of comparing k to idx. The second assertion was splitted into two to make constraints clearer. Applied changes requested by Matthias --- ...ng_constraint_generator_transformation.cpp | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/solvers/refinement/string_constraint_generator_transformation.cpp b/src/solvers/refinement/string_constraint_generator_transformation.cpp index f27fe5d4317..c110f636c43 100644 --- a/src/solvers/refinement/string_constraint_generator_transformation.cpp +++ b/src/solvers/refinement/string_constraint_generator_transformation.cpp @@ -36,22 +36,29 @@ string_exprt string_constraint_generatort::add_axioms_for_set_length( // We add axioms: // a1 : |res|=k - // a2 : forall i s[i]=s1[i]) &&(i >= k ==> s[i]=0) + // a2 : forall i<|s1|. i < |res| ==> res[i] = s1[i] + // a3 : forall i<|s1|. i >= |res| ==> res[i] = 0 axioms.push_back(res.axiom_for_has_length(k)); symbol_exprt idx=fresh_univ_index( "QA_index_set_length", ref_type.get_index_type()); string_constraintt a2( - idx, k, and_exprt( - implies_exprt( - s1.axiom_for_is_strictly_longer_than(idx), - equal_exprt(s1[idx], res[idx])), - implies_exprt( - s1.axiom_for_is_shorter_than(idx), - equal_exprt(s1[idx], constant_char(0, ref_type.get_char_type()))))); + idx, + s1.length(), + res.axiom_for_is_strictly_longer_than(idx), + equal_exprt(s1[idx], res[idx])); axioms.push_back(a2); + symbol_exprt idx2=fresh_univ_index( + "QA_index_set_length2", ref_type.get_index_type()); + string_constraintt a3( + idx2, + s1.length(), + res.axiom_for_is_shorter_than(idx2), + equal_exprt(res[idx2], constant_char(0, ref_type.get_char_type()))); + axioms.push_back(a3); + return res; } From 7cf1c92d44a81dcaf506a171e5ed01d6632933c9 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Fri, 7 Apr 2017 16:56:04 +0100 Subject: [PATCH 212/699] Fixes in pre-processing for issue #170 Do not force return type of StringBuilder functions This was causing some type problems because the return types and the lhs do not match. As a consequence some equalities were ignored by the string solver. Get rid of typecasts These are not needed and may result in incorrect type later. --- .../string_refine_preprocess.cpp | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/src/goto-programs/string_refine_preprocess.cpp b/src/goto-programs/string_refine_preprocess.cpp index f6e2b432c92..8e220d234d5 100644 --- a/src/goto-programs/string_refine_preprocess.cpp +++ b/src/goto-programs/string_refine_preprocess.cpp @@ -648,19 +648,15 @@ void string_refine_preprocesst::make_string_function( { if(signature.back()=='S') { - code_typet ft=function_type; - ft.return_type()=jls_ptr; - typecast_exprt lhs2(lhs, jls_ptr); - make_string_assign( goto_program, target, - lhs2, - ft, + lhs, + function_type, function_name, arguments, location, - signature); + signature); } else make_normal_assign( @@ -746,6 +742,7 @@ void string_refine_preprocesst::make_string_function( std::string new_sig=signature; exprt lhs; + if(assign_first_arg) { assert(!function_call.arguments().empty()); @@ -759,9 +756,6 @@ void string_refine_preprocesst::make_string_function( else lhs=function_call.lhs(); - if(lhs.id()==ID_typecast) - lhs=to_typecast_expr(lhs).op(); - new_type.return_type()=lhs.type(); make_string_function( @@ -1400,19 +1394,19 @@ void string_refine_preprocesst::initialize_string_function_table() signatures["java::java.lang.String.contains:(Ljava/lang/CharSequence;)Z"]= "SSZ"; signatures["java::java.lang.StringBuilder.insert:(IZ)" - "Ljava/lang/StringBuilder;"]="SIZS"; + "Ljava/lang/StringBuilder;"]="SIZ_"; signatures["java::java.lang.StringBuilder.insert:(IJ)" - "Ljava/lang/StringBuilder;"]="SIJS"; + "Ljava/lang/StringBuilder;"]="SIJ_"; signatures["java::java.lang.StringBuilder.insert:(II)" - "Ljava/lang/StringBuilder;"]="SIIS"; + "Ljava/lang/StringBuilder;"]="SII_"; signatures["java::java.lang.StringBuilder.insert:(IC)" - "Ljava/lang/StringBuilder;"]="SICS"; + "Ljava/lang/StringBuilder;"]="SIC_"; signatures["java::java.lang.StringBuilder.insert:(ILjava/lang/String;)" - "Ljava/lang/StringBuilder;"]="SISS"; + "Ljava/lang/StringBuilder;"]="SIS_"; signatures["java::java.lang.StringBuilder.insert:(ILjava/lang/String;)" - "Ljava/lang/StringBuilder;"]="SISS"; + "Ljava/lang/StringBuilder;"]="SIS_"; signatures["java::java.lang.StringBuilder.insert:(I[C)" - "Ljava/lang/StringBuilder;"]="SI[S"; + "Ljava/lang/StringBuilder;"]="SI[_"; signatures["java::java.lang.String.intern:()Ljava/lang/String;"]="SV"; } From 6b24ec76dbf83dc64f282ac20d82739f13958c21 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Thu, 13 Apr 2017 17:44:11 +0100 Subject: [PATCH 213/699] Implement StringBuffer methods Addresses issue diffblue/test-gen#245. This adds preprocessing for StringBuffer methods --- .../string_refine_preprocess.cpp | 151 +++++++++++++++++- src/goto-programs/string_refine_preprocess.h | 5 + 2 files changed, 153 insertions(+), 3 deletions(-) diff --git a/src/goto-programs/string_refine_preprocess.cpp b/src/goto-programs/string_refine_preprocess.cpp index f6e2b432c92..26abe8d2dc6 100644 --- a/src/goto-programs/string_refine_preprocess.cpp +++ b/src/goto-programs/string_refine_preprocess.cpp @@ -123,6 +123,44 @@ bool string_refine_preprocesst::is_java_string_builder_pointer_type( /*******************************************************************\ +Function: string_refine_preprocesst::is_java_string_buffer_type + + Inputs: a type + + Outputs: Boolean telling whether the type is that of java string buffer + +\*******************************************************************/ + +bool string_refine_preprocesst::is_java_string_buffer_type(const typet &type) +{ + return check_java_type(type, "java.lang.StringBuffer"); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::is_java_string_buffer_pointer_type + + Inputs: a type + + Outputs: Boolean telling whether the type is that of java StringBuffer + pointers + +\*******************************************************************/ + +bool string_refine_preprocesst::is_java_string_buffer_pointer_type( + const typet &type) +{ + if(type.id()==ID_pointer) + { + const pointer_typet &pt=to_pointer_type(type); + const typet &subtype=pt.subtype(); + return is_java_string_buffer_type(subtype); + } + return false; +} + +/*******************************************************************\ + Function: string_refine_preprocesst::is_java_char_sequence_type Inputs: a type @@ -315,9 +353,7 @@ Function: string_refine_preprocesst::get_data_and_length_type_of_string void string_refine_preprocesst::get_data_and_length_type_of_string( const exprt &expr, typet &data_type, typet &length_type) { - assert(is_java_string_type(expr.type()) || - is_java_string_builder_type(expr.type()) || - is_java_char_sequence_type(expr.type())); + assert(implements_java_char_sequence(pointer_typet(expr.type()))); typet object_type=ns.follow(expr.type()); const struct_typet &struct_type=to_struct_type(object_type); for(const auto &component : struct_type.components()) @@ -1351,6 +1387,115 @@ void string_refine_preprocesst::initialize_string_function_table() // Not supported "java.lang.StringBuilder.trimToSize" // TODO clean irep ids from insert_char_array etc... + // StringBuffer library + string_function_calls + ["java::java.lang.StringBuffer.:(Ljava/lang/String;)V"]= + ID_cprover_string_copy_func; + string_function_calls["java::java.lang.StringBuffer.:()V"]= + ID_cprover_string_empty_string_func; + + side_effect_functions + ["java::java.lang.StringBuffer.append:(Z)Ljava/lang/StringBuffer;"]= + ID_cprover_string_concat_bool_func; + side_effect_functions + ["java::java.lang.StringBuffer.append:(C)Ljava/lang/StringBuffer;"]= + ID_cprover_string_concat_char_func; + side_effect_functions + ["java::java.lang.StringBuffer.append:([C)" + "Ljava/lang/StringBuffer;"]= + ID_cprover_string_concat_func; + // Not supported: "java.lang.StringBuffer.append:([CII)" + // Not supported: "java.lang.StringBuffer.append:(LCharSequence;)" + side_effect_functions + ["java::java.lang.StringBuffer.append:(D)Ljava/lang/StringBuffer;"]= + ID_cprover_string_concat_double_func; + side_effect_functions + ["java::java.lang.StringBuffer.append:(F)Ljava/lang/StringBuffer;"]= + ID_cprover_string_concat_float_func; + side_effect_functions + ["java::java.lang.StringBuffer.append:(I)Ljava/lang/StringBuffer;"]= + ID_cprover_string_concat_int_func; + side_effect_functions + ["java::java.lang.StringBuffer.append:(J)Ljava/lang/StringBuffer;"]= + ID_cprover_string_concat_long_func; + // Not supported: "java.lang.StringBuffer.append:(LObject;)" + side_effect_functions + ["java::java.lang.StringBuffer.append:(Ljava/lang/String;)" + "Ljava/lang/StringBuffer;"]= + ID_cprover_string_concat_func; + side_effect_functions + ["java::java.lang.StringBuffer.appendCodePoint:(I)" + "Ljava/lang/StringBuffer;"]= + ID_cprover_string_concat_code_point_func; + // Not supported: "java.lang.StringBuffer.append:(Ljava/lang/StringBuffer;)" + // Not supported: "java.lang.StringBuffer.capacity:()" + string_functions["java::java.lang.StringBuffer.charAt:(I)C"]= + ID_cprover_string_char_at_func; + string_functions["java::java.lang.StringBuffer.codePointAt:(I)I"]= + ID_cprover_string_code_point_at_func; + string_functions["java::java.lang.StringBuffer.codePointBefore:(I)I"]= + ID_cprover_string_code_point_before_func; + string_functions["java::java.lang.StringBuffer.codePointCount:(II)I"]= + ID_cprover_string_code_point_count_func; + side_effect_functions + ["java::java.lang.StringBuffer.delete:(II)Ljava/lang/StringBuffer;"]= + ID_cprover_string_delete_func; + side_effect_functions + ["java::java.lang.StringBuffer.deleteCharAt:(I)Ljava/lang/StringBuffer;"]= + ID_cprover_string_delete_char_at_func; + // Not supported: "java.lang.StringBuffer.ensureCapacity:()" + // Not supported: "java.lang.StringBuffer.getChars:()" + // Not supported: "java.lang.StringBuffer.indexOf:()" + side_effect_functions + ["java::java.lang.StringBuffer.insert:(IZ)Ljava/lang/StringBuffer;"]= + ID_cprover_string_insert_bool_func; + side_effect_functions + ["java::java.lang.StringBuffer.insert:(IC)Ljava/lang/StringBuffer;"]= + ID_cprover_string_insert_char_func; + side_effect_functions + ["java::java.lang.StringBuffer.insert:(I[C)Ljava/lang/StringBuffer;"]= + ID_cprover_string_insert_func; + side_effect_functions + ["java::java.lang.StringBuffer.insert:(I[CII)Ljava/lang/StringBuffer;"]= + ID_cprover_string_insert_func; + // Not supported "java.lang.StringBuffer.insert:(ILCharSequence;)" + // Not supported "java.lang.StringBuffer.insert:(ILCharSequence;II)" + // Not supported "java.lang.StringBuffer.insert:(ID)" + // Not supported "java.lang.StringBuffer.insert:(IF)" + side_effect_functions + ["java::java.lang.StringBuffer.insert:(II)Ljava/lang/StringBuffer;"]= + ID_cprover_string_insert_int_func; + side_effect_functions + ["java::java.lang.StringBuffer.insert:(IJ)Ljava/lang/StringBuffer;"]= + ID_cprover_string_insert_long_func; + // Not supported "java.lang.StringBuffer.insert:(ILObject;)" + side_effect_functions + ["java::java.lang.StringBuffer.insert:(ILjava/lang/String;)" + "Ljava/lang/StringBuffer;"]= + ID_cprover_string_insert_func; + // Not supported "java.lang.StringBuffer.lastIndexOf" + string_functions["java::java.lang.StringBuffer.length:()I"]= + ID_cprover_string_length_func; + // Not supported "java.lang.StringBuffer.offsetByCodePoints" + // Not supported "java.lang.StringBuffer.replace" + // Not supported "java.lang.StringBuffer.reverse" + side_effect_functions["java::java.lang.StringBuffer.setCharAt:(IC)V"]= + ID_cprover_string_char_set_func; + side_effect_functions + ["java::java.lang.StringBuffer.setLength:(I)V"]= + ID_cprover_string_set_length_func; + // Not supported "java.lang.StringBuffer.subSequence" + string_functions + ["java::java.lang.StringBuffer.substring:(II)Ljava/lang/String;"]= + ID_cprover_string_substring_func; + string_functions + ["java::java.lang.StringBuffer.substring:(I)Ljava/lang/String;"]= + ID_cprover_string_substring_func; + string_functions + ["java::java.lang.StringBuffer.toString:()Ljava/lang/String;"]= + ID_cprover_string_copy_func; + // Not supported "java.lang.StringBuffer.trimToSize" + // Other libraries string_functions["java::java.lang.CharSequence.charAt:(I)C"]= ID_cprover_string_char_at_func; diff --git a/src/goto-programs/string_refine_preprocess.h b/src/goto-programs/string_refine_preprocess.h index 5ae398b757a..df419c73750 100644 --- a/src/goto-programs/string_refine_preprocess.h +++ b/src/goto-programs/string_refine_preprocess.h @@ -53,6 +53,10 @@ class string_refine_preprocesst:public messaget static bool is_java_string_builder_pointer_type(const typet &type); + static bool is_java_string_buffer_type(const typet &type); + + static bool is_java_string_buffer_pointer_type(const typet &type); + static bool is_java_char_sequence_type(const typet &type); static bool is_java_char_sequence_pointer_type(const typet &type); @@ -66,6 +70,7 @@ class string_refine_preprocesst:public messaget return is_java_char_sequence_pointer_type(type) || is_java_string_builder_pointer_type(type) || + is_java_string_buffer_pointer_type(type) || is_java_string_pointer_type(type); } From 2c78d4648103085d59348db07d3a1d5c7bcd55e7 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Thu, 13 Apr 2017 13:34:42 +0100 Subject: [PATCH 214/699] Correcting constraints for conversion from int diffblue/test-gen#241 The first two constraints that were previously added in add_axioms_from_int were not enough to ensure correctness. They are replaced here by: * a1 : i < 0 => 1 <|res|<=max_size && res[0]='-' * a2 : i >= 0 => 0 <|res|<=max_size-1 && '0'<=res[0]<='9' Clarifications in add_axioms_from_int diffblue/test-gen#241 We make the code clearer and add overflow checks. Corrections after Peter's review. --- .../string_constraint_generator_valueof.cpp | 155 +++++++----------- 1 file changed, 63 insertions(+), 92 deletions(-) diff --git a/src/solvers/refinement/string_constraint_generator_valueof.cpp b/src/solvers/refinement/string_constraint_generator_valueof.cpp index edff2d726e7..d967e5bb820 100644 --- a/src/solvers/refinement/string_constraint_generator_valueof.cpp +++ b/src/solvers/refinement/string_constraint_generator_valueof.cpp @@ -267,23 +267,6 @@ string_exprt string_constraint_generatort::add_axioms_from_bool( /*******************************************************************\ -Function: smallest_by_digit - - Inputs: number of digit - - Outputs: an integer with the right number of digit - - Purpose: gives the smallest integer with the specified number of digits - -\*******************************************************************/ - -static mp_integer smallest_by_digit(int nb) -{ - return power(10, nb-1); -} - -/*******************************************************************\ - Function: string_constraint_generatort::add_axioms_from_int Inputs: a signed integer expression, and a maximal size for the string @@ -313,102 +296,90 @@ string_exprt string_constraint_generatort::add_axioms_from_int( exprt max=from_integer(max_size, index_type); // We add axioms: - // a1 : 0 <|res|<=max_size - // a2 : (res[0]='-')||('0'<=res[0]<='9') - - and_exprt a1(res.axiom_for_is_strictly_longer_than(zero), - res.axiom_for_is_shorter_than(max)); + // a1 : i < 0 => 1 <|res|<=max_size && res[0]='-' + // a2 : i >= 0 => 0 <|res|<=max_size-1 && '0'<=res[0]<='9' + // a3 : |res|>1 && '0'<=res[0]<='9' => res[0]!='0' + // a4 : |res|>1 && res[0]='-' => res[1]!='0' + + binary_relation_exprt is_negative(i, ID_lt, zero); + and_exprt correct_length1( + res.axiom_for_is_strictly_longer_than(1), + res.axiom_for_is_shorter_than(max)); + equal_exprt starts_with_minus(res[0], minus_char); + implies_exprt a1(is_negative, and_exprt(correct_length1, starts_with_minus)); axioms.push_back(a1); - exprt chr=res[0]; - equal_exprt starts_with_minus(chr, minus_char); + not_exprt is_positive(is_negative); and_exprt starts_with_digit( - binary_relation_exprt(chr, ID_ge, zero_char), - binary_relation_exprt(chr, ID_le, nine_char)); - or_exprt a2(starts_with_digit, starts_with_minus); + binary_relation_exprt(res[0], ID_ge, zero_char), + binary_relation_exprt(res[0], ID_le, nine_char)); + and_exprt correct_length2( + res.axiom_for_is_strictly_longer_than(0), + res.axiom_for_is_strictly_shorter_than(max)); + implies_exprt a2(is_positive, and_exprt(correct_length2, starts_with_digit)); axioms.push_back(a2); - // These are constraints to detect number that requiere the maximum number - // of digits - exprt smallest_with_max_digits= - from_integer(smallest_by_digit(max_size-1), type); - binary_relation_exprt big_negative( - i, ID_le, unary_minus_exprt(smallest_with_max_digits)); - binary_relation_exprt big_positive(i, ID_ge, smallest_with_max_digits); - or_exprt requieres_max_digits(big_negative, big_positive); + implies_exprt a3( + and_exprt(res.axiom_for_is_strictly_longer_than(1), starts_with_digit), + not_exprt(equal_exprt(res[0], zero_char))); + axioms.push_back(a3); + + implies_exprt a4( + and_exprt(res.axiom_for_is_strictly_longer_than(1), starts_with_minus), + not_exprt(equal_exprt(res[1], zero_char))); + axioms.push_back(a4); + + assert(max_size::max()); for(size_t size=1; size<=max_size; size++) { // For each possible size, we add axioms: - // all_numbers: forall 1<=i<=size. '0'<=res[i]<='9' - // a3 : |res|=size&&'0'<=res[0]<='9' => - // i=sum+str[0]-'0' &&all_numbers - // a4 : |res|=size&&res[0]='-' => i=-sum - // a5 : size>1 => |res|=size&&'0'<=res[0]<='9' => res[0]!='0' - // a6 : size>1 => |res|=size&&res[0]'-' => res[1]!='0' - // a7 : size==max_size => i>1000000000 - exprt sum=from_integer(0, type); - exprt all_numbers=true_exprt(); - chr=res[0]; - exprt first_value=typecast_exprt(minus_exprt(chr, zero_char), type); + // a5 : forall 1 <= j < size. '0' <= res[j] <= '9' && sum == 10 * (sum/10) + // a6 : |res| == size && '0' <= res[0] <= '9' => i == sum + // a7 : |res| == size && res[0] == '-' => i == -sum + + exprt::operandst digit_constraints; + exprt sum=if_exprt( + starts_with_digit, + typecast_exprt(minus_exprt(res[0], zero_char), type), + from_integer(0, type)); for(size_t j=1; j=max_size-1) + { + // check for overflows if the size is big + and_exprt no_overflow( + equal_exprt(sum, div_exprt(ten_sum, ten)), + binary_relation_exprt(new_sum, ID_ge, ten_sum)); + digit_constraints.push_back(no_overflow); + } + sum=new_sum; } - axioms.push_back(all_numbers); + exprt a5=conjunction(digit_constraints); + axioms.push_back(a5); equal_exprt premise=res.axiom_for_has_length(size); - equal_exprt constr3(i, plus_exprt(sum, first_value)); - implies_exprt a3(and_exprt(premise, starts_with_digit), constr3); - axioms.push_back(a3); + implies_exprt a6( + and_exprt(premise, starts_with_digit), equal_exprt(i, sum)); + axioms.push_back(a6); - implies_exprt a4( + implies_exprt a7( and_exprt(premise, starts_with_minus), equal_exprt(i, unary_minus_exprt(sum))); - axioms.push_back(a4); - - // disallow 0s at the beginning - if(size>1) - { - equal_exprt r0_zero(res[zero], zero_char); - implies_exprt a5( - and_exprt(premise, starts_with_digit), - not_exprt(r0_zero)); - axioms.push_back(a5); - - exprt one=from_integer(1, index_type); - equal_exprt r1_zero(res[one], zero_char); - implies_exprt a6( - and_exprt(premise, starts_with_minus), - not_exprt(r1_zero)); - axioms.push_back(a6); - } - - // when the size is close to the maximum, either the number is very big - // or it is negative - if(size==max_size-1) - { - implies_exprt a7(premise, or_exprt(requieres_max_digits, - starts_with_minus)); - axioms.push_back(a7); - } - // when we reach the maximal size the number is very big in the negative - if(size==max_size) - { - implies_exprt a7(premise, and_exprt(starts_with_minus, big_negative)); - axioms.push_back(a7); - } + axioms.push_back(a7); } + return res; } From 43e324f39d103c56d0668dd9723ad437c1bd4bbb Mon Sep 17 00:00:00 2001 From: Dario Cattaruzza Date: Wed, 10 May 2017 09:47:28 +0100 Subject: [PATCH 215/699] Added new friend to bmc to handle refactoring There are two versions of bmc_cover (one in the private, one in the public repo). This new class will minimize duplicate code by using a templated version instead --- src/cbmc/bmc.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cbmc/bmc.h b/src/cbmc/bmc.h index b81b2d94c38..e923711a47e 100644 --- a/src/cbmc/bmc.h +++ b/src/cbmc/bmc.h @@ -110,6 +110,8 @@ class bmct:public safety_checkert friend class bmc_all_propertiest; friend class bmc_covert; + template