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;
   }
 };

Reply via email to