Fossil SCM
Fix floating-point divide by zero issue in TH1 reported on the mailing list and add tests.
Commit
479b3de1d201bf0b6880dc3b4dc82fe5a8c6d273
Parent
7a988eed376372e…
2 files changed
+9
-3
+20
M
src/th.c
+9
-3
| --- src/th.c | ||
| +++ src/th.c | ||
| @@ -1876,18 +1876,18 @@ | ||
| 1876 | 1876 | if( rc==TH_OK && eArgType==ARG_INTEGER ){ |
| 1877 | 1877 | int iRes = 0; |
| 1878 | 1878 | switch( pExpr->pOp->eOp ) { |
| 1879 | 1879 | case OP_MULTIPLY: iRes = iLeft*iRight; break; |
| 1880 | 1880 | case OP_DIVIDE: |
| 1881 | - if(!iRight){ | |
| 1881 | + if( !iRight ){ | |
| 1882 | 1882 | Th_ErrorMessage(interp, "Divide by 0:", zLeft, nLeft); |
| 1883 | 1883 | return TH_ERROR; |
| 1884 | 1884 | } |
| 1885 | 1885 | iRes = iLeft/iRight; |
| 1886 | 1886 | break; |
| 1887 | 1887 | case OP_MODULUS: |
| 1888 | - if(!iRight){ | |
| 1888 | + if( !iRight ){ | |
| 1889 | 1889 | Th_ErrorMessage(interp, "Modulo by 0:", zLeft, nLeft); |
| 1890 | 1890 | return TH_ERROR; |
| 1891 | 1891 | } |
| 1892 | 1892 | iRes = iLeft%iRight; |
| 1893 | 1893 | break; |
| @@ -1913,11 +1913,17 @@ | ||
| 1913 | 1913 | } |
| 1914 | 1914 | Th_SetResultInt(interp, iRes); |
| 1915 | 1915 | }else if( rc==TH_OK && eArgType==ARG_NUMBER ){ |
| 1916 | 1916 | switch( pExpr->pOp->eOp ) { |
| 1917 | 1917 | case OP_MULTIPLY: Th_SetResultDouble(interp, fLeft*fRight); break; |
| 1918 | - case OP_DIVIDE: Th_SetResultDouble(interp, fLeft/fRight); break; | |
| 1918 | + case OP_DIVIDE: | |
| 1919 | + if( fRight==0.0 ){ | |
| 1920 | + Th_ErrorMessage(interp, "Divide by 0:", zLeft, nLeft); | |
| 1921 | + return TH_ERROR; | |
| 1922 | + } | |
| 1923 | + Th_SetResultDouble(interp, fLeft/fRight); | |
| 1924 | + break; | |
| 1919 | 1925 | case OP_ADD: Th_SetResultDouble(interp, fLeft+fRight); break; |
| 1920 | 1926 | case OP_SUBTRACT: Th_SetResultDouble(interp, fLeft-fRight); break; |
| 1921 | 1927 | case OP_LT: Th_SetResultInt(interp, fLeft<fRight); break; |
| 1922 | 1928 | case OP_GT: Th_SetResultInt(interp, fLeft>fRight); break; |
| 1923 | 1929 | case OP_LE: Th_SetResultInt(interp, fLeft<=fRight); break; |
| 1924 | 1930 |
| --- src/th.c | |
| +++ src/th.c | |
| @@ -1876,18 +1876,18 @@ | |
| 1876 | if( rc==TH_OK && eArgType==ARG_INTEGER ){ |
| 1877 | int iRes = 0; |
| 1878 | switch( pExpr->pOp->eOp ) { |
| 1879 | case OP_MULTIPLY: iRes = iLeft*iRight; break; |
| 1880 | case OP_DIVIDE: |
| 1881 | if(!iRight){ |
| 1882 | Th_ErrorMessage(interp, "Divide by 0:", zLeft, nLeft); |
| 1883 | return TH_ERROR; |
| 1884 | } |
| 1885 | iRes = iLeft/iRight; |
| 1886 | break; |
| 1887 | case OP_MODULUS: |
| 1888 | if(!iRight){ |
| 1889 | Th_ErrorMessage(interp, "Modulo by 0:", zLeft, nLeft); |
| 1890 | return TH_ERROR; |
| 1891 | } |
| 1892 | iRes = iLeft%iRight; |
| 1893 | break; |
| @@ -1913,11 +1913,17 @@ | |
| 1913 | } |
| 1914 | Th_SetResultInt(interp, iRes); |
| 1915 | }else if( rc==TH_OK && eArgType==ARG_NUMBER ){ |
| 1916 | switch( pExpr->pOp->eOp ) { |
| 1917 | case OP_MULTIPLY: Th_SetResultDouble(interp, fLeft*fRight); break; |
| 1918 | case OP_DIVIDE: Th_SetResultDouble(interp, fLeft/fRight); break; |
| 1919 | case OP_ADD: Th_SetResultDouble(interp, fLeft+fRight); break; |
| 1920 | case OP_SUBTRACT: Th_SetResultDouble(interp, fLeft-fRight); break; |
| 1921 | case OP_LT: Th_SetResultInt(interp, fLeft<fRight); break; |
| 1922 | case OP_GT: Th_SetResultInt(interp, fLeft>fRight); break; |
| 1923 | case OP_LE: Th_SetResultInt(interp, fLeft<=fRight); break; |
| 1924 |
| --- src/th.c | |
| +++ src/th.c | |
| @@ -1876,18 +1876,18 @@ | |
| 1876 | if( rc==TH_OK && eArgType==ARG_INTEGER ){ |
| 1877 | int iRes = 0; |
| 1878 | switch( pExpr->pOp->eOp ) { |
| 1879 | case OP_MULTIPLY: iRes = iLeft*iRight; break; |
| 1880 | case OP_DIVIDE: |
| 1881 | if( !iRight ){ |
| 1882 | Th_ErrorMessage(interp, "Divide by 0:", zLeft, nLeft); |
| 1883 | return TH_ERROR; |
| 1884 | } |
| 1885 | iRes = iLeft/iRight; |
| 1886 | break; |
| 1887 | case OP_MODULUS: |
| 1888 | if( !iRight ){ |
| 1889 | Th_ErrorMessage(interp, "Modulo by 0:", zLeft, nLeft); |
| 1890 | return TH_ERROR; |
| 1891 | } |
| 1892 | iRes = iLeft%iRight; |
| 1893 | break; |
| @@ -1913,11 +1913,17 @@ | |
| 1913 | } |
| 1914 | Th_SetResultInt(interp, iRes); |
| 1915 | }else if( rc==TH_OK && eArgType==ARG_NUMBER ){ |
| 1916 | switch( pExpr->pOp->eOp ) { |
| 1917 | case OP_MULTIPLY: Th_SetResultDouble(interp, fLeft*fRight); break; |
| 1918 | case OP_DIVIDE: |
| 1919 | if( fRight==0.0 ){ |
| 1920 | Th_ErrorMessage(interp, "Divide by 0:", zLeft, nLeft); |
| 1921 | return TH_ERROR; |
| 1922 | } |
| 1923 | Th_SetResultDouble(interp, fLeft/fRight); |
| 1924 | break; |
| 1925 | case OP_ADD: Th_SetResultDouble(interp, fLeft+fRight); break; |
| 1926 | case OP_SUBTRACT: Th_SetResultDouble(interp, fLeft-fRight); break; |
| 1927 | case OP_LT: Th_SetResultInt(interp, fLeft<fRight); break; |
| 1928 | case OP_GT: Th_SetResultInt(interp, fLeft>fRight); break; |
| 1929 | case OP_LE: Th_SetResultInt(interp, fLeft<=fRight); break; |
| 1930 |
+20
| --- test/th1.test | ||
| +++ test/th1.test | ||
| @@ -65,5 +65,25 @@ | ||
| 65 | 65 | |
| 66 | 66 | ############################################################################### |
| 67 | 67 | |
| 68 | 68 | fossil test-th-eval --th-open-config "setting -strict -- --" |
| 69 | 69 | test th1-setting-10 {$RESULT eq {TH_ERROR: no value for setting "--"}} |
| 70 | + | |
| 71 | +############################################################################### | |
| 72 | + | |
| 73 | +fossil test-th-eval "expr 42/0" | |
| 74 | +test th1-divide-by-zero-1 {$RESULT eq {TH_ERROR: Divide by 0: 42}} | |
| 75 | + | |
| 76 | +############################################################################### | |
| 77 | + | |
| 78 | +fossil test-th-eval "expr 42/0.0" | |
| 79 | +test th1-divide-by-zero-2 {$RESULT eq {TH_ERROR: Divide by 0: 42}} | |
| 80 | + | |
| 81 | +############################################################################### | |
| 82 | + | |
| 83 | +fossil test-th-eval "expr 42.0/0" | |
| 84 | +test th1-divide-by-zero-3 {$RESULT eq {TH_ERROR: Divide by 0: 42.0}} | |
| 85 | + | |
| 86 | +############################################################################### | |
| 87 | + | |
| 88 | +fossil test-th-eval "expr 42.0/0.0" | |
| 89 | +test th1-divide-by-zero-4 {$RESULT eq {TH_ERROR: Divide by 0: 42.0}} | |
| 70 | 90 |
| --- test/th1.test | |
| +++ test/th1.test | |
| @@ -65,5 +65,25 @@ | |
| 65 | |
| 66 | ############################################################################### |
| 67 | |
| 68 | fossil test-th-eval --th-open-config "setting -strict -- --" |
| 69 | test th1-setting-10 {$RESULT eq {TH_ERROR: no value for setting "--"}} |
| 70 |
| --- test/th1.test | |
| +++ test/th1.test | |
| @@ -65,5 +65,25 @@ | |
| 65 | |
| 66 | ############################################################################### |
| 67 | |
| 68 | fossil test-th-eval --th-open-config "setting -strict -- --" |
| 69 | test th1-setting-10 {$RESULT eq {TH_ERROR: no value for setting "--"}} |
| 70 | |
| 71 | ############################################################################### |
| 72 | |
| 73 | fossil test-th-eval "expr 42/0" |
| 74 | test th1-divide-by-zero-1 {$RESULT eq {TH_ERROR: Divide by 0: 42}} |
| 75 | |
| 76 | ############################################################################### |
| 77 | |
| 78 | fossil test-th-eval "expr 42/0.0" |
| 79 | test th1-divide-by-zero-2 {$RESULT eq {TH_ERROR: Divide by 0: 42}} |
| 80 | |
| 81 | ############################################################################### |
| 82 | |
| 83 | fossil test-th-eval "expr 42.0/0" |
| 84 | test th1-divide-by-zero-3 {$RESULT eq {TH_ERROR: Divide by 0: 42.0}} |
| 85 | |
| 86 | ############################################################################### |
| 87 | |
| 88 | fossil test-th-eval "expr 42.0/0.0" |
| 89 | test th1-divide-by-zero-4 {$RESULT eq {TH_ERROR: Divide by 0: 42.0}} |
| 90 |