Menu

#1206 Intrinsic function EXP

GC 3.x
accepted
nobody
4
2026-03-18
2026-03-13
No

Hi
The following code generate this message
GNU MP: Cannot allocate memory (size=9223372036854775928)
Aborted (core dumped)

       IDENTIFICATION DIVISION.
       PROGRAM-ID . stuff .
      *>
       ENVIRONMENT DIVISION.
       DATA DIVISION .
       WORKING-STORAGE  SECTION.

       01 A               PIC 9(38) COMP-3      .

      *>
       PROCEDURE DIVISION .
      *>------------------
      *>
           move 99999999999999999999999 TO A .
           DISPLAY FUNCTION EXP(A) .
           GOBACK .

In the cob_mpf_exp function, it is necessary to check the input value to avoid a crash of libgmp and to raise an exception if it is outside an acceptable range.
Denis

Discussion

  • Simon Sobisch

    Simon Sobisch - 2026-03-13
    • labels: --> GMP overflow, intrinsic, EXP, EXP10
    • status: open --> accepted
    • Priority: 5 - default --> 4
     
  • Simon Sobisch

    Simon Sobisch - 2026-03-13

    That also applies to FUNCTION EXP10 - but we may not get an abort there as we stay with strict cob_decimal (mpz) types, while EXP works internally on mpf (floating-point) and conversions between that and mpz are "costly" (computing time and memory).

    When checking the standard I've found there is no general maximum value but the following rule matches as well:

    The evaluation of a function produces a returned value in a temporary elementary data item. If the length of the returned value exceeds the maximum length specified by the implementor for a returned value, an EC-ARGUMENT-FUNCTION exception condition is set to exist.

    ... but cob_mpf_exp() doesn't know where it come from and it seems to be more reasonable for that specific case to check in cob_intr_exp, either before or after calling cob_decimal_get_mpf().

    @dhugonnard Could you have a look at a testcase for EXP and EXP10 that shows a huge number that should be handled correctly (which likely means: cut by overflow/underflow when moving to a variable) and a slightly bigger one that doesn't (and currently either aborts or just takes a long time / memory to produce no reasonable value)?
    Then we can also have a look how to tackle that best.

     
  • Denis HUGONNARD-ROCHE

    Hi Simon
    The limits I found on my PC (Ubuntu WSL on Windows) are in the program.
    Although these numbers don't cause crashes, they don't make much sense.

    We should set limits that take into account the precision handled by gnucobol, which is given by COB_MAX_INTERMEDIATE_FLOATING_SIZE, which is 96.

    For exponential values, we start losing precision from 222 (222/LN(10) > 96).
    Furthermore, according to the manual, the FLOAT-LONG values ​​can go up to 1.797693134862316 * 10^308.

    I think we should set an arbitrary limit that takes these parameters into account. For the limit, I propose [-512;512].

           IDENTIFICATION DIVISION.
           PROGRAM-ID . stuff .
          *>
           ENVIRONMENT DIVISION.
           DATA DIVISION .
           WORKING-STORAGE  SECTION.
    
           01 A   PIC         S9(38) COMP-3   .
    
          *>
           PROCEDURE DIVISION .
          *>------------------
          *>
          *>       EXP FUNCTION
    
          *    core dumped
          *    move                   99999 TO A .
    
    
          *    don't crash
               move                    9999 TO A .
               DISPLAY FUNCTION EXP(A) .
    
          *>       EXP(10) FUNCTION
    
          *    core
          *    move               999999999 TO A .
          *    move                99999999 TO A .
          *    move                 9999999 TO A .
    
    
          *    don't crash
               move                  999999 TO A .
               DISPLAY FUNCTION EXP10(A) .
               GOBACK .
    

    Denis

     
  • Denis HUGONNARD-ROCHE

    NB : For the factorial function, I have a crash starting at 9274

     
  • Simon Sobisch

    Simon Sobisch - 2026-03-14

    Thanks for working on this! Rechecking with gcobol those functions, if too big, yield INF - which we could do as well (possibly additional to raising the exception - which doesn't do anything if the exception check is not enabled).

    Do you get different results with decimals - e.g. .99999? Taking this into account was the one part where I've told myself "this needs testing, not just some limit put in".
    In theory we could add a check on the data size = mpz_size(d.value)...

     
  • Denis HUGONNARD-ROCHE

    hi Simon

    Here is the piece of code to handle EXP function.
    when i test it's ok i have the right value and the display FUNCTION EXCEPTION-STATUS give the good one.
    What i don't understand :
    i compile with --fec=all
    I expected an abort of the program like subscript out of bound
    Denis

        /* #1206 Avoid GMP Crash */
        if ( mpf_cmp_ui(cob_mpft, COB_MAX_EXP_LIMIT) >= 0 || mpf_cmp_si (cob_mpft, COB_MIN_EXP_LIMIT) <= 0) {
                if (mpf_sgn (cob_mpft) > 0) {
    
                    mpf_set_ui(cob_mpft, 0UL) ;
    
                    cob_set_exception (COB_EC_ARGUMENT_FUNCTION);
                    cob_decimal_set_mpf (&d1, cob_mpft);
                    d1.scale = COB_DECIMAL_INF;
                    cob_alloc_field (&d1);
                    (void)cob_decimal_get_field (&d1, curr_field, 0);
    
                    return curr_field;
    
                } else {
                    mpf_set_ui(cob_mpft, COB_MIN_EXP_MANTISSA);
                    cob_set_exception (COB_EC_ARGUMENT_FUNCTION);
    
                    cob_decimal_set_mpf (&d1, cob_mpft);
                    d1.scale = COB_MIN_EXP_SCALE ;
    
                    cob_alloc_field (&d1);
                    (void)cob_decimal_get_field (&d1, curr_field, 0);
    
                    return curr_field;
                }
        }
    
     
    • Simon Sobisch

      Simon Sobisch - 2026-03-16

      I expected an abort of the program like subscript out of bound

      Not all arguments are fatal but... EC-ARGUMENT-FUNCTION is.

      Checked: cobc currently does not generate COB_EC_ARGUMENT_FUNCTION checks at all, so that needs to be added to codegen.c, most likely in output_param() the end of case CB_TAG_INTRINSIC:, in a if (CB_EXCEPTION_ENABLE (COB_EC_ARGUMENT_FUNCTION)) { check... but that's a "general" side issue.

      I'd suggest that you finish your code changes on this issue (EXP+EXP10) one (most of the code in the last post is identical and therefore can be moved to after the inner condition check + test in run_functions.at + Changelog) to a clean PR or patch file, to allow me to easily add it.

      Your code looks well and the test sound like exactly what we need.

       
  • Denis HUGONNARD-ROCHE

    Hi Simon i have almost finished ...
    A question how in a cobol program test that the result is COB_DECIMAL_INF ?

    Denis

     
    • Simon Sobisch

      Simon Sobisch - 2026-03-18

      Most likely "not yet".

      You should be able to:

      IF float-ITEM IS NOT FLOAT-INFINITY CONTINUE.
      IF float-ITEM IS NOT FLOAT-NOT-A-NUMBER CONTINUE.
      IF float-ITEM IS NOT FLOAT-NOT-A-NUMBER-QUIET CONTINUE.
      IF float-ITEM IS NOT FLOAT-NOT-A-NUMBER-SIGNALING CONTINUE.
      SET float-item TO FLOAT-INFINITY
      SET float-item TO FLOAT-INFINITY SIGN POSITIVE
      SET float-item TO FLOAT-INFINITY SIGN NEGATIVE
      SET float-item TO FLOAT-NOT-A-NUMBER
      SET float-item TO FLOAT-NOT-A-NUMBER SIGN POSITIVE
      SET float-item TO FLOAT-NOT-A-NUMBER SIGN NEGATIVE
      SET float-item TO FLOAT-NOT-A-NUMBER-SIGNALING
      SET float-item TO FLOAT-NOT-A-NUMBER-SIGNALING SIGN POSITIVE
      SET float-item TO FLOAT-NOT-A-NUMBER-SIGNALING SIGN NEGATIVE
      

      ... but we don't have those words even reserved.

      But that actually should be easy to add - would you like to create a separate patch for this?
      If you don't know how, then we can do that together (presumably with some GSoC applicants).

       
  • Denis HUGONNARD-ROCHE

    ok yes i prefere do another patch as when those features will be implemented we will update the testsuite

     

Log in to post a comment.

MongoDB Logo MongoDB