https://gcc.gnu.org/g:fcd6b4f2f8cf7c0ff9002eec048d4bd724334476
commit r17-4168-gfcd6b4f2f8cf7c0ff9002eec048d4bd724334476 Author: James K. Lowden <[email protected]> Date: Thu Sep 10 11:59:37 2026 -0400 cobol: Correct use-after-free error in ADD CORRESPONDING. gcc/cobol/ChangeLog: * parse.y: Construct arith_t by value. * parse_ante.h (struct arith_t): Use const reference for constructor. (struct refer_list_t): Prefer initialization to std::copy. Diff: --- gcc/cobol/parse.y | 24 ++++++++++++------------ gcc/cobol/parse_ante.h | 12 +++++------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/gcc/cobol/parse.y b/gcc/cobol/parse.y index 1cc16f575c29..e064ef99dc2f 100644 --- a/gcc/cobol/parse.y +++ b/gcc/cobol/parse.y @@ -6186,7 +6186,7 @@ end_add: %empty %prec ADD add_body: sum TO rnames { - $$ = new arith_t(@sum, no_giving_e, $sum); + $$ = new arith_t(@sum, no_giving_e, *$sum); std::copy( rhs.begin(), rhs.end(), back_inserter($$->tgts) ); $$->locs.tgts = @rnames; @@ -6194,7 +6194,7 @@ add_body: sum TO rnames } | sum TO num_operand[value] GIVING rnames { - $$ = new arith_t(@$, giving_e, $sum); + $$ = new arith_t(@$, giving_e, *$sum); $$->A.push_back(*$value); std::copy( rhs.begin(), rhs.end(), back_inserter($$->tgts) ); @@ -6203,7 +6203,7 @@ add_body: sum TO rnames } | sum GIVING rnames { // implicit TO - $$ = new arith_t(@sum, giving_e, $sum); + $$ = new arith_t(@sum, giving_e, *$sum); std::copy( rhs.begin(), rhs.end(), back_inserter($$->tgts) ); $$->locs.tgts = @rnames; @@ -6222,7 +6222,7 @@ add_body: sum TO rnames } // First src/tgt elements are templates. // Their subscripts apply to the correspondents. - $$ = new arith_t(@sum, corresponding_e, $sum); + $$ = new arith_t(@sum, corresponding_e, *$sum); $$->tgts.push_front(rhs.front()); $$->locs.tgts = @rnames; // use arith_t functor to populate A and tgts @@ -8878,7 +8878,7 @@ end_subtract: %empty %prec SUBTRACT subtract_body: sum FROM rnames { - $$ = new arith_t(@sum, no_giving_e, $sum); + $$ = new arith_t(@sum, no_giving_e, *$sum); std::copy( rhs.begin(), rhs.end(), back_inserter($$->tgts) ); $$->locs.tgts = @rnames; @@ -8886,7 +8886,7 @@ subtract_body: sum FROM rnames } | sum FROM num_operand[input] GIVING rnames { - $$ = new arith_t(@sum, giving_e, $sum); + $$ = new arith_t(@sum, giving_e, *$sum); $$->B.push_back(*$input); $$->locs.B = @input; std::copy( rhs.begin(), @@ -8907,7 +8907,7 @@ subtract_body: sum FROM rnames } // First src/tgt elements are templates. // Their subscripts apply to the correspondents. - $$ = new arith_t(@sum, corresponding_e, $sum); + $$ = new arith_t(@sum, corresponding_e, *$sum); $$->tgts.push_front(rhs.front()); $$->locs.tgts = @rnames; // use arith_t functor to populate A and tgts @@ -13855,13 +13855,13 @@ valid_pointer_relop( const cbl_loc_t& lloc, } arith_t::arith_t( const cbl_loc_t& loc, - cbl_arith_format_t format, refer_list_t * refers ) - : format(format), on_error(NULL), not_error(NULL) + cbl_arith_format_t format, const refer_list_t& refers ) + : format(format) + , A(refers.refers.begin(), refers.refers.end()) + , on_error(NULL) + , not_error(NULL) { - std::copy( refers->refers.begin(), refers->refers.end(), back_inserter(A) ); - refers->refers.clear(); locs.A = loc; - delete refers; } cbl_key_t::cbl_key_t( sort_key_t that ) diff --git a/gcc/cobol/parse_ante.h b/gcc/cobol/parse_ante.h index 9fbc139f391a..54a4f90b86b4 100644 --- a/gcc/cobol/parse_ante.h +++ b/gcc/cobol/parse_ante.h @@ -604,7 +604,7 @@ struct arith_t { : format(format), on_error(NULL), not_error(NULL) {} arith_t( const cbl_loc_t& loc, - cbl_arith_format_t format, refer_list_t * refers ); + cbl_arith_format_t format, const refer_list_t& refers ); bool corresponding() const { return format == corresponding_e; } @@ -1308,9 +1308,8 @@ struct refer_list_t { } } // the source is not always to be deleted - explicit refer_list_t( const cbl_refer_t& refer ) { - refers.push_back(refer); - } + explicit refer_list_t( const cbl_refer_t& refer ) : refers(1, refer) {} + refer_list_t * push_back( cbl_refer_t *refer ) { refers.push_back(*refer); delete refer; @@ -1333,10 +1332,9 @@ struct refer_list_t { } std::vector<cbl_refer_t> vectorize() { - std::vector<cbl_refer_t> tgt(refers.size()); - std::copy(refers.begin(), refers.end(), tgt.begin()); + std::vector<cbl_refer_t> output(refers.begin(), refers.end()); refers.clear(); - return tgt; + return output; } };
