From ad975d539e1357f62b4e6501c2252490dbb9f43b Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 27 Apr 2016 15:24:13 +0000 Subject: [PATCH] More simplification of the sqlite3AtoF() routine. Add special comments to indicate branches that are for optimization purposes only and that give the correct answer even if always or never taken. FossilOrigin-Name: 0065fe97cb8e5076acae1bf1560fd2f69dab9014 --- manifest | 12 ++++---- manifest.uuid | 2 +- src/util.c | 77 ++++++++++++++++++++++++++++++--------------------- 3 files changed, 52 insertions(+), 39 deletions(-) diff --git a/manifest b/manifest index 06c6814c38..7fa7ebedf8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sstill\smore\sunnecessary\sbranches\sfrom\ssqlite3AtoF(). -D 2016-04-27T02:35:03.572 +C More\ssimplification\sof\sthe\ssqlite3AtoF()\sroutine.\s\sAdd\sspecial\scomments\nto\sindicate\sbranches\sthat\sare\sfor\soptimization\spurposes\sonly\sand\sthat\sgive\nthe\scorrect\sanswer\seven\sif\salways\sor\snever\staken. +D 2016-04-27T15:24:13.573 F Makefile.in 9e816d0323e418fbc0f8b2c05fc14e0b3763d9e8 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 71b8b16cf9393f68e2e2035486ca104872558836 @@ -441,7 +441,7 @@ F src/treeview.c e4b41a37530a191579d3c53142cc44ee2eb99373 F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c 3e67ab3c0814635f355fb1f8ab010a2b9e016e7d F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c -F src/util.c 562f7a85d933b7173a29e331deb28d85d6208f7c +F src/util.c d0899604c30b4a9d493980aa7742eeda383fff6d F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 F src/vdbe.c d3843a66d74a7696477ee5141e5eb9a7e5e2401c F src/vdbe.h 5591b5add447096e31288b5a0a78ec5d7b5c5170 @@ -1484,7 +1484,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P dd69e53cb077873171af5312c633ca185595bf31 -R 4f22b05e3bc28723a991a2f87c87962e +P 3adfe9f3e6ce7cc09fcb570d9b65e830a96cac15 +R 676347b15924e075b34cabb43dd7e840 U drh -Z 439e39a464407086f87a7be758f8e1c8 +Z 680dc6a7c6e0d675cd4dc0c16abcab9d diff --git a/manifest.uuid b/manifest.uuid index 1f512c3c71..a6a5e1cabb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3adfe9f3e6ce7cc09fcb570d9b65e830a96cac15 \ No newline at end of file +0065fe97cb8e5076acae1bf1560fd2f69dab9014 \ No newline at end of file diff --git a/src/util.c b/src/util.c index c85ae6a199..1f59a9f731 100644 --- a/src/util.c +++ b/src/util.c @@ -355,7 +355,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ int eValid = 1; /* True exponent is either not used or is well-formed */ double result; int nDigits = 0; - int nonNum = 0; + int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */ assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); *pResult = 0.0; /* Default return value, in case of an error */ @@ -368,7 +368,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); for(i=3-enc; i=zEnd ) goto do_atof_calc; + + /* This branch is needed to avoid a (harmless) buffer overread. The + ** special comment alerts the mutation tester that the correct answer + ** is obtained even if the branch is omitted */ + if( z>=zEnd ) goto do_atof_calc; /*PREVENTS-HARMLESS-OVERREAD*/ + /* get sign of exponent */ if( *z=='-' ){ esign = -1; @@ -443,41 +448,51 @@ do_atof_calc: esign = 1; } - /* if 0 significand */ - if( !s ) { - /* In the IEEE 754 standard, zero is signed. - ** Add the sign if we've seen at least one digit */ + if( s==0 ) { + /* In the IEEE 754 standard, zero is signed. */ result = sign<0 ? -(double)0 : (double)0; } else { - /* attempt to reduce exponent */ - if( esign>0 ){ - while( s<(LARGEST_INT64/10) && e>0 ) e--,s*=10; - }else{ - while( !(s%10) && e>0 ) e--,s/=10; + /* Attempt to reduce exponent. + ** + ** Branches that are not required for the correct answer but which only + ** help to obtain the correct answer faster are marked with special + ** comments, as a hint to the mutation tester. + */ + while( e>0 ){ /*OPTIMIZATION-IF-TRUE*/ + if( esign>0 ){ + if( s>=(LARGEST_INT64/10) ) break; /*OPTIMIZATION-IF-FALSE*/ + s *= 10; + }else{ + if( s%10!=0 ) break; /*OPTIMIZATION-IF-FALSE*/ + s /= 10; + } + e--; } /* adjust the sign of significand */ s = sign<0 ? -s : s; - /* if exponent, scale significand as appropriate - ** and store in result. */ - if( e ){ + if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/ + result = (double)s; + }else{ LONGDOUBLE_TYPE scale = 1.0; /* attempt to handle extremely small/large numbers better */ - if( e>307 && e<342 ){ - while( e%308 ) { scale *= 1.0e+1; e -= 1; } - if( esign<0 ){ - result = s / scale; - result /= 1.0e+308; - }else{ - result = s * scale; - result *= 1.0e+308; - } - }else if( e>=342 ){ - if( esign<0 ){ - result = 0.0*s; - }else{ - result = 1e308*1e308*s; /* Infinity */ + if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/ + if( e<342 ){ /*OPTIMIZATION-IF-TRUE*/ + while( e%308 ) { scale *= 1.0e+1; e -= 1; } + if( esign<0 ){ + result = s / scale; + result /= 1.0e+308; + }else{ + result = s * scale; + result *= 1.0e+308; + } + }else{ assert( e>=342 ); + if( esign<0 ){ + result = 0.0*s; + }else{ + result = 1e308*1e308*s; /* Infinity */ + } } }else{ /* 1.0e+22 is the largest power of 10 than can be @@ -490,8 +505,6 @@ do_atof_calc: result = s * scale; } } - } else { - result = (double)s; } } @@ -499,7 +512,7 @@ do_atof_calc: *pResult = result; /* return true if number and no extra non-whitespace chracters after */ - return z>=zEnd && nDigits>0 && eValid && nonNum==0; + return z==zEnd && nDigits>0 && eValid && nonNum==0; #else return !sqlite3Atoi64(z, pResult, length, enc); #endif /* SQLITE_OMIT_FLOATING_POINT */