#67 UDF: Modifying literal arguments causes segfaults.

unclassified
accepted
nobody
UDF (1)
6
2014-11-05
2014-02-22
Edward Hart
No

Modifying arguments which are given literal values results in a segfault.

Here is an example program which causes the problem:

       >>SOURCE FREE
IDENTIFICATION DIVISION.
PROGRAM-ID. test-prog.

ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
REPOSITORY.
    FUNCTION add-two
    .
PROCEDURE DIVISION.
    DISPLAY add-two(2)
    .
END PROGRAM test-prog.

IDENTIFICATION DIVISION.
FUNCTION-ID. add-two.

DATA DIVISION.
LINKAGE SECTION.
01  arg                                 PIC 9(5) COMP.

01  ret                                 PIC 9(5) COMP.

PROCEDURE DIVISION USING arg RETURNING ret.
    ADD 2 TO arg GIVING arg, ret
    .
END FUNCTION add-two.

cobc -info:

cobc (GNU Cobol) 2.0.0
Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Keisuke Nishida
Copyright (C) 2006-2012 Roger While
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Built     Jan 03 2014 15:06:26
Packaged  Feb 11 2012 12:36:31 UTC
C version "4.8.1"
Build information
Build environment        : x86_64-unknown-linux-gnu
CC                       : gcc -std=gnu99
CPPFLAGS                 : 
CFLAGS                   : -O2 -pipe -finline-functions -fsigned-char
                           -Wall -Wwrite-strings -Wmissing-prototypes
                           -Wno-format-y2k -U_FORTIFY_SOURCE
LD                       : /usr/bin/ld -m elf_x86_64
LDFLAGS                  : -Wl,-z,relro,-z,now,-O1

GNU Cobol information
COB_CC                   : gcc -std=gnu99
COB_CFLAGS               : -I/usr/local/include -pipe
COB_LDFLAGS              : 
COB_LIBS                 : -L/usr/local/lib -lcob -lm -lgmp -lncursesw
                           -ldb -ldl
COB_CONFIG_DIR           : /usr/local/share/gnu-cobol/config
COB_COPY_DIR             : /usr/local/share/gnu-cobol/copy
COB_LIBRARY_PATH         : /usr/local/lib/gnu-cobol
COB_MODULE_EXT           : so
COB_EXEEXT               : 
Dynamic loading          : System
"CBL_" param check       : Disabled
Variable format          : 0
BINARY-C-LONG            : 8 bytes
Sequential handler       : Internal
ISAM handler             : BDB

Discussion

  • Simon Sobisch
    Simon Sobisch
    2014-02-22

    • labels: --> UDF
    • summary: Modifying literal arguments causes segfaults. --> UDF: Modifying literal arguments causes segfaults.
    • status: open --> accepted
    • Priority: 1 --> 6
     
  • Simon Sobisch
    Simon Sobisch
    2014-02-22

    Thank you for reporting this.
    I think the compiler should error modifying the using parameter (as this is simple in this case).

    I think this only occurs with UDF or is this true for a normal sub program, too?

    A small information is missing:
    What is the output from this program when compiled with/without -debug?

    Simon

     
  • Edward Hart
    Edward Hart
    2014-02-23

    I think this only occurs with UDF or is this true for a normal sub program, too?

    A segfault occurs with UDFs but not with subprograms - they seem to happily work with whatever junk value they end up with. For example, if I pass 2 to the following program, 54434 is always displayed:

    IDENTIFICATION DIVISION.
    PROGRAM-ID. add-two.
    
    DATA DIVISION.
    LINKAGE SECTION.
    01  arg                                 PIC 9(5) COMP.
    
    PROCEDURE DIVISION USING arg.
        ADD 2 TO arg
        DISPLAY arg
        .
    END PROGRAM add-two.
    

    What is the output from this program when compiled with/without -debug?

    With -debug, it says the segfault occurs on line 25 (the ADD statement). To be precise, the segfault occurs here in the .c file:

    cob_decimal_add (d0, d1);
    cob_decimal_get_field (d0, COB_SET_DATA (f_10, b_10), 4); /* this statement */
    

    I think the compiler should error modifying the using parameter (as this is simple in this case)

    May I ask why? I thought that literals were passed BY CONTENT, meaning that the called subprogram/UDF can then modify a local copy of it.

     
  • My two bits. Take with salt:

    Literals must be passed BY CONTENT. There's no other safe way to do so.

    The receiving code can be in a separately compiled module, and thus has no way of knowing that the value passed is a literal or otherwise.

    The literal is likely embedded in the literal pool (if GNU Cobol has one) which can be embedded in a code page (at least by some compilers on MVS). So the literal cannot be safely passed as-is.

    Generally, passing by CONTENT means that the calling module provides a copy of the value to be passed. This cannot be a reference to the original, and the caller pays the overhead. This way the called module doesn't need to know how the value was passed. If it is failing with a segment fault, then I would think that the literal value is being incorrectly passed BY REFERENCE. That would be a compiler error, if that is really what is going on.

    Does this help?

     
  • Simon Sobisch
    Simon Sobisch
    2014-03-07

    Just to add this information: using current version of gnu-cobol-2.0 with gcc 4.8.2 on i686-pc-cygwin does not result in a segfault (both C and CPP versions).

    There are different problems with non-display data types in all 2.x versions (always use -debug to at least see the issue), but this is another issue which will be filed later (the fix is kind of in-progress).

    Simon

     
  • Simon Sobisch
    Simon Sobisch
    2014-03-07

    Works here if usage display is used:

           >>SOURCE FREE
    IDENTIFICATION DIVISION.
    PROGRAM-ID. prog.
    
    ENVIRONMENT DIVISION.
    CONFIGURATION SECTION.
    REPOSITORY.
        FUNCTION add-two
        .
        WORKING-STORAGE SECTION.
        77 two pic 9(05) value 2 comp-5.
    PROCEDURE DIVISION.
        DISPLAY 'F' add-two('00002')
        call 'padd-two' using '00003'
        .
    END PROGRAM prog.
    
    IDENTIFICATION DIVISION.
    FUNCTION-ID. add-two.
    
    DATA DIVISION.
    LINKAGE SECTION.
    01  arg.
        05 arg-9                            PIC 9(5).
    
    01  ret                                 PIC 9(5).
    
    PROCEDURE DIVISION USING arg RETURNING ret.
        ADD 2 TO arg-9 GIVING arg-9, ret
        .
    END FUNCTION add-two.
    
    IDENTIFICATION DIVISION.
    PROGRAM-ID. padd-two.
    
    DATA DIVISION.
    LINKAGE SECTION.
    01  arg2.
        05 arg2-9                            PIC 9(5).
    
    PROCEDURE DIVISION USING arg2.
        ADD 2 TO arg2-9 
        DISPLAY 'P' arg2-9
        .
    END PROGRAM padd-two.
    

    And another info:
    There surely is a bug with the 'literal pool' (or more likely with cob_save_func/cob_restore_func): if you change the above string '00003' to '00002' you'll get a result of 'P00006' ;-) (as the same constant was changed before from '00002' to '00006').

    Simon