https://gcc.gnu.org/g:1be9a0f45e0ba43c44d80a60ea770e4eb330917f
commit r17-2419-g1be9a0f45e0ba43c44d80a60ea770e4eb330917f Author: James K. Lowden <[email protected]> Date: Wed Jul 15 11:11:55 2026 -0400 cobol: Correct tests against uninitialized access and other incorrect behavior. Some tests wrote to an input parameter to NUL-terminate a filename. Some did not set RETURN-CODE to zero before returning. MF-specific tests are now also tested with the gcobc script to ensure compatibility. gcc/cobol/ChangeLog: * parse.y: Add debug messages during parameter validation. * symbols.h: (cbl_ffi_arg_t::capacity_ok): New function. libgcobol/ChangeLog: * compat/gnu/lib/CBL_CREATE_FILE.cbl: Do not write to input parameter. * compat/gnu/lib/CBL_OPEN_FILE.cbl: Same. gcc/testsuite/ChangeLog: * cobol.dg/group2/CBL_CREATE_FILE___CBL_WRITE_FILE___CBL_CLOSE_FILE.cob: Add gcobc. * cobol.dg/group2/CBL_DELETE_FILE.cob: Same. * cobol.dg/group2/CBL_OPEN_FILE___CBL_CLOSE_FILE.cob: Same. * cobol.dg/group2/CBL_OPEN_FILE___CBL_READ_FILE___CBL_CLOSE_FILE.cob: Same. * cobol.dg/group2/CBL_READ_FILE__check_file_size_with_flags___128.cob: Same. * cobol.dg/.gitignore: New test. Diff: --- gcc/cobol/parse.y | 11 +++++--- gcc/cobol/symbols.h | 6 +++++ gcc/testsuite/cobol.dg/.gitignore | 1 + ...EATE_FILE___CBL_WRITE_FILE___CBL_CLOSE_FILE.cob | 2 +- gcc/testsuite/cobol.dg/group2/CBL_DELETE_FILE.cob | 1 + .../group2/CBL_OPEN_FILE___CBL_CLOSE_FILE.cob | 4 +-- ..._OPEN_FILE___CBL_READ_FILE___CBL_CLOSE_FILE.cob | 2 +- ...READ_FILE__check_file_size_with_flags___128.cob | 2 ++ libgcobol/compat/gnu/lib/CBL_CREATE_FILE.cbl | 28 +++++++++++++++------ libgcobol/compat/gnu/lib/CBL_OPEN_FILE.cbl | 29 +++++++++++++++++++--- 10 files changed, 68 insertions(+), 18 deletions(-) diff --git a/gcc/cobol/parse.y b/gcc/cobol/parse.y index 8213520980a0..60fa04603731 100644 --- a/gcc/cobol/parse.y +++ b/gcc/cobol/parse.y @@ -12745,7 +12745,7 @@ cbl_ffi_arg_t::matches( const cbl_ffi_arg_t& that ) const { case by_reference_e: if( crv == by_reference_e ) { if( (formal->attr & mask) == (actual->attr & mask) ) { - if( formal->data.capacity() == actual->data.capacity() ) { + if( capacity_ok(formal, actual) ) { if( formal->type == actual->type ) { // captures USAGE except COMP-X return true; } @@ -12754,13 +12754,17 @@ cbl_ffi_arg_t::matches( const cbl_ffi_arg_t& that ) const { return true; } } - // If actual is by reference, so must the formal be. + // If actual is by reference, so must the formal be. + dbgmsg("%s:%d: failed, reference feature mismatch", __func__, __LINE__); return false; break; case by_content_e: break; case by_value_e: - if( crv != by_value_e ) return false; + if( crv != by_value_e ) { + dbgmsg("%s:%d: failed, actual %s not by value", __func__, __LINE__, actual->name); + return false; + } if( formal->type == FldPointer && that.refer.is_pointer() ) return true; break; } @@ -12777,6 +12781,7 @@ cbl_ffi_arg_t::matches( const cbl_ffi_arg_t& that ) const { return actual->data.capacity() == formal->data.capacity() && actual->codeset.encoding == formal->codeset.encoding; } + dbgmsg("%s:%d: failed, for some reason", __func__, __LINE__); return false; } diff --git a/gcc/cobol/symbols.h b/gcc/cobol/symbols.h index 408a8a5f1043..3bb84a11d354 100644 --- a/gcc/cobol/symbols.h +++ b/gcc/cobol/symbols.h @@ -1411,6 +1411,12 @@ protected: if( crv == by_reference_e ) return false; return refer.field != NULL; } + static bool capacity_ok( const cbl_field_t *formal, const cbl_field_t *actual ) { + if( formal->data.capacity() == actual->data.capacity() ) return true; + if( formal->data.capacity() == 1 && formal->has_attr(any_length_e) ) return true; + if( actual->data.capacity() == 1 && actual->has_attr(any_length_e) ) return true; + return false; + } }; // In support of serial/linear search: diff --git a/gcc/testsuite/cobol.dg/.gitignore b/gcc/testsuite/cobol.dg/.gitignore new file mode 100644 index 000000000000..93e59d108ce4 --- /dev/null +++ b/gcc/testsuite/cobol.dg/.gitignore @@ -0,0 +1 @@ +*.txt0 diff --git a/gcc/testsuite/cobol.dg/group2/CBL_CREATE_FILE___CBL_WRITE_FILE___CBL_CLOSE_FILE.cob b/gcc/testsuite/cobol.dg/group2/CBL_CREATE_FILE___CBL_WRITE_FILE___CBL_CLOSE_FILE.cob index 0154889ebd03..55d6582f75ce 100644 --- a/gcc/testsuite/cobol.dg/group2/CBL_CREATE_FILE___CBL_WRITE_FILE___CBL_CLOSE_FILE.cob +++ b/gcc/testsuite/cobol.dg/group2/CBL_CREATE_FILE___CBL_WRITE_FILE___CBL_CLOSE_FILE.cob @@ -1,5 +1,5 @@ *> { dg-do run } - *> { dg-options "-dialect mf" } + *> { dg-options "-dialect mf -fcobol-exceptions EC-ALL" } identification division. program-id. test_cbl_write_file. diff --git a/gcc/testsuite/cobol.dg/group2/CBL_DELETE_FILE.cob b/gcc/testsuite/cobol.dg/group2/CBL_DELETE_FILE.cob index 66febc97d6a5..a9096a06177f 100644 --- a/gcc/testsuite/cobol.dg/group2/CBL_DELETE_FILE.cob +++ b/gcc/testsuite/cobol.dg/group2/CBL_DELETE_FILE.cob @@ -21,6 +21,7 @@ perform create-file. perform delete-file. perform delete-invalid-file. + move zero to return-code. goback. create-file section. diff --git a/gcc/testsuite/cobol.dg/group2/CBL_OPEN_FILE___CBL_CLOSE_FILE.cob b/gcc/testsuite/cobol.dg/group2/CBL_OPEN_FILE___CBL_CLOSE_FILE.cob index dbf8b650dd40..68cb44e55146 100644 --- a/gcc/testsuite/cobol.dg/group2/CBL_OPEN_FILE___CBL_CLOSE_FILE.cob +++ b/gcc/testsuite/cobol.dg/group2/CBL_OPEN_FILE___CBL_CLOSE_FILE.cob @@ -41,13 +41,13 @@ open-ro. move 1 to access-mode. display "Opening /dev/null as read-only" - call "CBL_OPEN_FILE" using "/dev/null" + call "CBL_OPEN_FILE" using Z"/dev/null" access-mode deny-mode device file-handle if return-code <> 0 - display "Failed to open " FILE_NAME " with " return-code + display "Failed to open " Z"/dev/null" " with " return-code else call "CBL_CLOSE_FILE" using file-handle end-if. diff --git a/gcc/testsuite/cobol.dg/group2/CBL_OPEN_FILE___CBL_READ_FILE___CBL_CLOSE_FILE.cob b/gcc/testsuite/cobol.dg/group2/CBL_OPEN_FILE___CBL_READ_FILE___CBL_CLOSE_FILE.cob index 75b53a188608..e1b5cf6bf758 100644 --- a/gcc/testsuite/cobol.dg/group2/CBL_OPEN_FILE___CBL_READ_FILE___CBL_CLOSE_FILE.cob +++ b/gcc/testsuite/cobol.dg/group2/CBL_OPEN_FILE___CBL_READ_FILE___CBL_CLOSE_FILE.cob @@ -35,7 +35,7 @@ *> Deny both read and write. move 0 to deny-mode. display "Opening /dev/zero as read-only". - call "CBL_OPEN_FILE" using "/dev/zero" + call "CBL_OPEN_FILE" using Z"/dev/zero" access-mode deny-mode device diff --git a/gcc/testsuite/cobol.dg/group2/CBL_READ_FILE__check_file_size_with_flags___128.cob b/gcc/testsuite/cobol.dg/group2/CBL_READ_FILE__check_file_size_with_flags___128.cob index 7772897ab40b..53763c624adf 100644 --- a/gcc/testsuite/cobol.dg/group2/CBL_READ_FILE__check_file_size_with_flags___128.cob +++ b/gcc/testsuite/cobol.dg/group2/CBL_READ_FILE__check_file_size_with_flags___128.cob @@ -29,6 +29,7 @@ procedure division. perform write-file. perform check-file-size. + move zero to return-code. goback. write-file section. @@ -77,6 +78,7 @@ file-handle. if return-code <> 0 + display "Failed to open file " filename display "CBL_OPEN_FILE failed with " return-code goback end-if. diff --git a/libgcobol/compat/gnu/lib/CBL_CREATE_FILE.cbl b/libgcobol/compat/gnu/lib/CBL_CREATE_FILE.cbl index 911bde060fa4..c1d6c5ebb378 100644 --- a/libgcobol/compat/gnu/lib/CBL_CREATE_FILE.cbl +++ b/libgcobol/compat/gnu/lib/CBL_CREATE_FILE.cbl @@ -47,18 +47,20 @@ 77 func-ret Binary-Long. 77 errno-val Binary-Long. 77 lk-mode PIC 9(8) COMP-5. + 01 filename-max CONSTANT AS 8 * 1024. + 01 filename PIC X(filename-max). 77 filename-len PIC 9(4) BINARY VALUE ZERO. 01 ws-access-mode PIC 9(8) COMP-5. LINKAGE SECTION. 77 RETCODE PIC X(2) COMP-5. - 01 filename PIC X ANY LENGTH. + 01 Lk-filename PIC X ANY LENGTH. 01 access-mode PIC x COMP-x. 01 deny-mode PIC x comp-x. *> Not supported (must be 0). 01 device PIC x comp-x. *> Not supported (must be 0). 01 file-handle PIC X(4) COMP-5. - PROCEDURE DIVISION USING filename, + PROCEDURE DIVISION USING Lk-filename, By Reference access-mode, By Reference deny-mode, By Reference device, @@ -72,8 +74,7 @@ END-IF. COMPUTE filename-len = - FUNCTION LENGTH(FUNCTION TRIM(filename)). - MOVE X"00" TO filename(filename-len + 1:1). + FUNCTION LENGTH(FUNCTION TRIM(Lk-filename)). D Display 'CBL_CREATE_FILE: filename: [' filename ']' D Display 'ws-access-mode: ' ws-access-mode ', ' D Display 'deny-mode: ' deny-mode. @@ -94,18 +95,31 @@ Compute ws-access-mode = ws-access-mode + O_CREAT + O_TRUNC. Compute Lk-mode = S_IRUSR + S_IWUSR + S_IRGRP + S_IWGRP. - MOVE FUNCTION posix-open(filename, ws-access-mode, lk-mode) - TO func-ret. + IF Lk-filename(filename-len:1) = ZERO + MOVE FUNCTION posix-open(Lk-filename, + ws-access-mode, lk-mode) + TO func-ret + ELSE + IF filename-max < filename-len + 1 + MOVE 30 to RETCODE + GOBACK + END-IF + MOVE Lk-filename to filename + MOVE ZERO TO filename(filename-len + 1:1) + MOVE FUNCTION posix-open(filename, ws-access-mode, lk-mode) + TO func-ret + END-IF If func-ret is < 0 Then Move Function COBRT-FILE-STATUS() to RETCODE D Display 'COBRT-FILE-STATUS returned: ' RETCODE + D ' for errno ' func-ret else Move func-ret to file-handle Move 0 to RETCODE end-if. - + END PROGRAM CBL_CREATE_FILE. >> POP SOURCE FORMAT diff --git a/libgcobol/compat/gnu/lib/CBL_OPEN_FILE.cbl b/libgcobol/compat/gnu/lib/CBL_OPEN_FILE.cbl index 0cc616453ae1..2c9a83085075 100644 --- a/libgcobol/compat/gnu/lib/CBL_OPEN_FILE.cbl +++ b/libgcobol/compat/gnu/lib/CBL_OPEN_FILE.cbl @@ -48,18 +48,21 @@ WORKING-STORAGE SECTION. 77 errno-val Binary-Long. 01 ws-access-mode PIC 9(8) comp-5. + 01 filename-max CONSTANT AS 8 * 1024. + 01 filename PIC X(filename-max). + 77 filename-len PIC 9(4) BINARY VALUE ZERO. LINKAGE SECTION. 01 RETCODE PIC X(2) COMP-5 VALUE 0. 01 REDEFINES RETCODE. 03 MSB PIC X. 03 LSB BINARY-CHAR. - 01 filename PIC X ANY LENGTH. + 01 Lk-filename PIC X ANY LENGTH. 01 access-mode PIC X COMP-X. 01 deny-mode PIC X COMP-X. *> Not supported (must be 0). 01 device PIC X COMP-X. *> Not supported (must be 0). 01 file-handle PIC X(4) COMP-5. - PROCEDURE DIVISION USING filename, + PROCEDURE DIVISION USING Lk-filename, By Reference access-mode, By Reference deny-mode, By Reference device, @@ -88,8 +91,26 @@ GOBACK END-EVALUATE. - MOVE FUNCTION posix-open(filename, ws-access-mode, deny-mode) - TO errno-val. + COMPUTE filename-len = + FUNCTION LENGTH(FUNCTION TRIM(Lk-filename)). + + * If Lk-filename ends in NUL, use it ... + IF Lk-filename(filename-len:1) = ZERO + MOVE FUNCTION posix-open(Lk-filename, + ws-access-mode, deny-mode) + TO errno-val + * ... else make a copy and terminate it with a NUL, unless it's too long. + ELSE + IF filename-max < filename-len + 1 + MOVE 30 to RETCODE + GOBACK + END-IF + MOVE Lk-filename to filename + MOVE ZERO TO filename(filename-len + 1:1) + MOVE FUNCTION posix-open(filename, + ws-access-mode, deny-mode) + TO errno-val + END-IF. D Display 'CBL_OPEN_FILE: RETCODE: ' RETCODE. If errno-val is < 0 then
