From 5fb3db4558cb09de8cc837da18276b8ffebf85ec Mon Sep 17 00:00:00 2001 From: Landon Curt Noll Date: Sun, 30 Sep 2018 14:08:20 -0700 Subject: [PATCH] Fixed trigonometric and hyperbolic core dumps --- CHANGES | 22 ++++++++++- cal/regress.cal | 18 +++++---- calcerr.tbl | 25 +++++++++++++ func.c | 99 +++++++++++++++++++++++++++++++++++++++---------- 4 files changed, 137 insertions(+), 27 deletions(-) diff --git a/CHANGES b/CHANGES index 7355376..ca7a040 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,24 @@ -The following are the changes from calc version 2.12.6.6 to date: +The following are the changes from calc version 2.12.6.9 to date: + + Fixed a number of core dump bugs related to the calculation of + tan(), cot(), sec(), csc(), tanh(), coth(), sech(), and csch(), + asin(), acos(), asinh(), acosh(), where when a call to an + underlying function produced an invalid value. Thanks goes to + github user wuxiuheng for reporting this problem. + + A number of trigonometric and hyperbolic functions that incorrectly + returned E_LOGINF, now return a new error code that is more + specific to the trigonometric or hyperbolic function. The + following is a list of these new error codes: E_TAN3 E_TAN4 + E_COT3 E_COT4 E_SEC3 E_CSC3 E_TANH3 E_TANH4 E_COTH3 E_COTH4 + E_SECH3 E_CSCH3 E_ASIN3 E_ACOS3 E_ASINH3 E_ACOSH3 E_ATAN3 E_ACOT3 + E_ASEC3 E_ACSC3 E_ATANH3 E_ACOTH3 E_ASECH3 E_ACSCH3. + + Added regression tests 3729 thru 3732 to test E_TAN3, E_COT3, + E_SEC3 and E_CSC3 respectively. + + +The following are the changes from calc version 2.12.6.6 to 2.12.6.8: For historical purposes, in lucas.cal, gen_v1(1, n) always returns 4. diff --git a/cal/regress.cal b/cal/regress.cal index 1fb1eee..f67eeda 100644 --- a/cal/regress.cal +++ b/cal/regress.cal @@ -3227,9 +3227,9 @@ define test_error() print '3600: Beginning test_error'; - /* bump ecnt up by 148 */ - ecnt += 148; - print '3601: ecnt += 148'; + /* bump ecnt up by 156 */ + ecnt += 156; + print '3601: ecnt += 156'; strx = "x"; print '3602: strx = "x"'; @@ -3418,11 +3418,15 @@ define test_error() n = 8191; print '3727: n = 8191'; /* test 3728 removed due to non-portable strerror() output */ + vrfy(tan(2e9i) == error(10435), '3729: tan(2e9i) == error(10435)'); + vrfy(cot(2e9i) == error(10437), '3730: cot(2e9i) == error(10437)'); + vrfy(sec(2e9i) == error(10439), '3731: sec(2e9i) == error(10439)'); + vrfy(csc(2e9i) == error(10440), '3732: csc(2e9i) == error(10440)'); /* errmax and errcount should be bumped up the 148 errors above */ - vrfy(errcount() == ecnt, '3729: errcount() == ecnt'); + vrfy(errcount() == ecnt, '3733: errcount() == ecnt'); - print '3730: Ending test_error'; + print '3734: Ending test_error'; } print '054: parsed test_error()'; @@ -7932,8 +7936,8 @@ print '8901: read -once "test8900"'; read -once "test8900"; print '8902: about to run test8900(1,,8903)'; testnum = test8900(1,,8903); -print '8999: ecnt = 203;' -ecnt = 203; +print '8999: ecnt = 211;' +ecnt = 211; /* 89xx: test calc resource functions by Christoph Zurnieden */ diff --git a/calcerr.tbl b/calcerr.tbl index 759b914..eb1db3a 100644 --- a/calcerr.tbl +++ b/calcerr.tbl @@ -451,6 +451,7 @@ E_FPATHOPEN1 Non-string arguments for fpathopen E_FPATHOPEN2 Unrecognized mode for fpathopen E_LOG1 Bad epsilon argument for log E_LOG2 Non-numeric first argument for log +E_LOG3 Cannot calculate log for this value E_FGETFILE1 Non-file argument for fgetfile E_FGETFILE2 File argument for fgetfile not open for reading E_FGETFILE3 Unable to set file position in fgetfile @@ -471,3 +472,27 @@ E_ISSPACE Bad argument for isspace E_ISXDIGIT Bad argument for isxdigit E_STRTOUPPER Bad argument type for strtoupper E_STRTOLOWER Bad argument type for strtolower +E_TAN3 Invalid value for calculating the sin numerator for tan +E_TAN4 Invalid value for calculating the cos denominator for tan +E_COT3 Invalid value for calculating the sin numerator for cot +E_COT4 Invalid value for calculating the cos denominator for cot +E_SEC3 Invalid value for calculating the cos reciprocal for sec +E_CSC3 Invalid value for calculating the sin reciprocal for csc +E_TANH3 Invalid value for calculating the sinh numerator for tanh +E_TANH4 Invalid value for calculating the cosh denominator for tanh +E_COTH3 Invalid value for calculating the sinh numerator for coth +E_COTH4 Invalid value for calculating the cosh denominator for coth +E_SECH3 Invalid value for calculating the cosh reciprocal for sech +E_CSCH3 Invalid value for calculating the sinh reciprocal for csch +E_ASIN3 Invalid value for calculating asin +E_ACOS3 Invalid value for calculating acos +E_ASINH3 Invalid value for calculating asinh +E_ACOSH3 Invalid value for calculating acosn +E_ATAN3 Invalid value for calculating atan +E_ACOT3 Invalid value for calculating acot +E_ASEC3 Invalid value for calculating asec +E_ACSC3 Invalid value for calculating acsc +E_ATANH3 Invalid value for calculating atan +E_ACOTH3 Invalid value for calculating acot +E_ASECH3 Invalid value for calculating asec +E_ACSCH3 Invalid value for calculating acsc diff --git a/func.c b/func.c index 7ae68b2..6f8ebb0 100644 --- a/func.c +++ b/func.c @@ -2122,6 +2122,9 @@ f_log(int count, VALUE **vals) default: return error_value(E_LOG2); } + if (c == NULL) { + return error_value(E_LOG3); + } result.v_type = V_COM; result.v_com = c; if (cisreal(c)) { @@ -2239,8 +2242,15 @@ f_tan(int count, VALUE **vals) case V_COM: tmp1.v_type = V_COM; tmp1.v_com = c_sin(vals[0]->v_com, err); + if (tmp1.v_com == NULL) { + return error_value(E_TAN3); + } tmp2.v_type = V_COM; tmp2.v_com = c_cos(vals[0]->v_com, err); + if (tmp2.v_com == NULL) { + comfree(tmp1.v_com); + return error_value(E_TAN4); + } divvalue(&tmp1, &tmp2, &result); comfree(tmp1.v_com); comfree(tmp2.v_com); @@ -2276,6 +2286,9 @@ f_sec(int count, VALUE **vals) case V_COM: tmp.v_type = V_COM; tmp.v_com = c_cos(vals[0]->v_com, err); + if (tmp.v_com == NULL) { + return error_value(E_SEC3); + } invertvalue(&tmp, &result); comfree(tmp.v_com); break; @@ -2314,8 +2327,15 @@ f_cot(int count, VALUE **vals) case V_COM: tmp1.v_type = V_COM; tmp1.v_com = c_cos(vals[0]->v_com, err); + if (tmp1.v_com == NULL) { + return error_value(E_COT3); + } tmp2.v_type = V_COM; tmp2.v_com = c_sin(vals[0]->v_com, err); + if (tmp2.v_com == NULL) { + comfree(tmp1.v_com); + return error_value(E_COT4); + } divvalue(&tmp1, &tmp2, &result); comfree(tmp1.v_com); comfree(tmp2.v_com); @@ -2354,6 +2374,9 @@ f_csc(int count, VALUE **vals) case V_COM: tmp.v_type = V_COM; tmp.v_com = c_sin(vals[0]->v_com, err); + if (tmp.v_com == NULL) { + return error_value(E_CSC3); + } invertvalue(&tmp, &result); comfree(tmp.v_com); break; @@ -2476,8 +2499,15 @@ f_tanh(int count, VALUE **vals) case V_COM: tmp1.v_type = V_COM; tmp1.v_com = c_sinh(vals[0]->v_com, err); + if (tmp1.v_com == NULL) { + return error_value(E_TANH3); + } tmp2.v_type = V_COM; tmp2.v_com = c_cosh(vals[0]->v_com, err); + if (tmp2.v_com == NULL) { + comfree(tmp1.v_com); + return error_value(E_TANH4); + } divvalue(&tmp1, &tmp2, &result); comfree(tmp1.v_com); comfree(tmp2.v_com); @@ -2517,8 +2547,15 @@ f_coth(int count, VALUE **vals) case V_COM: tmp1.v_type = V_COM; tmp1.v_com = c_cosh(vals[0]->v_com, err); + if (tmp1.v_com == NULL) { + return error_value(E_COTH3); + } tmp2.v_type = V_COM; tmp2.v_com = c_sinh(vals[0]->v_com, err); + if (tmp2.v_com == NULL) { + comfree(tmp1.v_com); + return error_value(E_COTH4); + } divvalue(&tmp1, &tmp2, &result); comfree(tmp1.v_com); comfree(tmp2.v_com); @@ -2555,6 +2592,9 @@ f_sech(int count, VALUE **vals) case V_COM: tmp.v_type = V_COM; tmp.v_com = c_cosh(vals[0]->v_com, err); + if (tmp.v_com == NULL) { + return error_value(E_SECH3); + } invertvalue(&tmp, &result); comfree(tmp.v_com); break; @@ -2592,6 +2632,9 @@ f_csch(int count, VALUE **vals) case V_COM: tmp.v_type = V_COM; tmp.v_com = c_sinh(vals[0]->v_com, err); + if (tmp.v_com == NULL) { + return error_value(E_CSCH3); + } invertvalue(&tmp, &result); comfree(tmp.v_com); break; @@ -2626,7 +2669,7 @@ f_atan(int count, VALUE **vals) case V_COM: tmp = c_atan(vals[0]->v_com, err); if (tmp == NULL) - return error_value(E_LOGINF); + return error_value(E_ATAN3); result.v_type = V_COM; result.v_com = tmp; if (cisreal(tmp)) { @@ -2666,7 +2709,7 @@ f_acot(int count, VALUE **vals) case V_COM: tmp = c_acot(vals[0]->v_com, err); if (tmp == NULL) - return error_value(E_LOGINF); + return error_value(E_ACOT3); result.v_type = V_COM; result.v_com = tmp; if (cisreal(tmp)) { @@ -2718,6 +2761,9 @@ f_asin(int count, VALUE **vals) default: return error_value(E_ASIN2); } + if (result.v_com == NULL) { + return error_value(E_ASIN3); + } if (result.v_type == V_COM && cisreal(result.v_com)) { q = qlink(result.v_com->real); comfree(result.v_com); @@ -2764,6 +2810,9 @@ f_acos(int count, VALUE **vals) default: return error_value(E_ACOS2); } + if (result.v_com == NULL) { + return error_value(E_ACOS3); + } if (result.v_type == V_COM && cisreal(result.v_com)) { q = qlink(result.v_com->real); comfree(result.v_com); @@ -2794,7 +2843,7 @@ f_asec(int count, VALUE **vals) switch (vals[0]->v_type) { case V_NUM: if (qiszero(vals[0]->v_num)) - return error_value(E_LOGINF); + return error_value(E_ASEC3); result.v_num = qasec(vals[0]->v_num, err); result.v_type = V_NUM; if (result.v_num == NULL) { @@ -2813,9 +2862,10 @@ f_asec(int count, VALUE **vals) default: return error_value(E_ASEC2); } + if (result.v_com == NULL) { + return error_value(E_ASEC3); + } if (result.v_type == V_COM) { - if (result.v_com == NULL) - return error_value(E_LOGINF); if (cisreal(result.v_com)) { q = qlink(result.v_com->real); comfree(result.v_com); @@ -2847,7 +2897,7 @@ f_acsc(int count, VALUE **vals) switch (vals[0]->v_type) { case V_NUM: if (qiszero(vals[0]->v_num)) - return error_value(E_LOGINF); + return error_value(E_ACSC3); result.v_num = qacsc(vals[0]->v_num, err); result.v_type = V_NUM; if (result.v_num == NULL) { @@ -2866,9 +2916,10 @@ f_acsc(int count, VALUE **vals) default: return error_value(E_ACSC2); } + if (result.v_com == NULL) { + return error_value(E_ACSC3); + } if (result.v_type == V_COM) { - if (result.v_com == NULL) - return error_value(E_LOGINF); if (cisreal(result.v_com)) { q = qlink(result.v_com->real); comfree(result.v_com); @@ -2903,6 +2954,9 @@ f_asinh(int count, VALUE **vals) break; case V_COM: tmp = c_asinh(vals[0]->v_com, err); + if (tmp == NULL) { + return error_value(E_ASINH3); + } result.v_type = V_COM; result.v_com = tmp; if (cisreal(tmp)) { @@ -2955,6 +3009,9 @@ f_acosh(int count, VALUE **vals) default: return error_value(E_ACOSH2); } + if (result.v_com == NULL) { + return error_value(E_ACOSH3); + } if (result.v_type == V_COM && cisreal(result.v_com)) { q = qlink(result.v_com->real); comfree(result.v_com); @@ -3002,9 +3059,10 @@ f_atanh(int count, VALUE **vals) default: return error_value(E_ATANH2); } + if (result.v_com == NULL) { + return error_value(E_ATANH3); + } if (result.v_type == V_COM) { - if (result.v_com == NULL) - return error_value(E_LOGINF); if (cisreal(result.v_com)) { q = qlink(result.v_com->real); comfree(result.v_com); @@ -3053,9 +3111,10 @@ f_acoth(int count, VALUE **vals) default: return error_value(E_ACOTH2); } + if (result.v_com == NULL) { + return error_value(E_ACOTH3); + } if (result.v_type == V_COM) { - if (result.v_com == NULL) - return error_value(E_LOGINF); if (cisreal(result.v_com)) { q = qlink(result.v_com->real); comfree(result.v_com); @@ -3087,7 +3146,7 @@ f_asech(int count, VALUE **vals) switch (vals[0]->v_type) { case V_NUM: if (qiszero(vals[0]->v_num)) - return error_value(E_LOGINF); + return error_value(E_ASECH3); result.v_num = qasech(vals[0]->v_num, err); result.v_type = V_NUM; if (result.v_num == NULL) { @@ -3106,9 +3165,10 @@ f_asech(int count, VALUE **vals) default: return error_value(E_ASECH2); } + if (result.v_com == NULL) { + return error_value(E_ASECH3); + } if (result.v_type == V_COM) { - if (result.v_com == NULL) - return error_value(E_LOGINF); if (cisreal(result.v_com)) { q = qlink(result.v_com->real); comfree(result.v_com); @@ -3140,7 +3200,7 @@ f_acsch(int count, VALUE **vals) switch (vals[0]->v_type) { case V_NUM: if (qiszero(vals[0]->v_num)) - return error_value(E_LOGINF); + return error_value(E_ACSCH3); result.v_num = qacsch(vals[0]->v_num, err); result.v_type = V_NUM; if (result.v_num == NULL) { @@ -3159,9 +3219,10 @@ f_acsch(int count, VALUE **vals) default: return error_value(E_ACSCH2); } + if (result.v_com == NULL) { + return error_value(E_ACSCH3); + } if (result.v_type == V_COM) { - if (result.v_com == NULL) - return error_value(E_LOGINF); if (cisreal(result.v_com)) { q = qlink(result.v_com->real); comfree(result.v_com); @@ -3260,7 +3321,7 @@ f_agd(int count, VALUE **vals) return error_value(E_AGD2); } if (result.v_com == NULL) - return error_value(E_AGD3); + return error_value(E_AGD3); if (cisreal(result.v_com)) { q = qlink(result.v_com->real); comfree(result.v_com);