From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1062) id 4C84B395B066; Mon, 12 Dec 2022 08:59:39 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4C84B395B066 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Alan Modra To: bfd-cvs@sourceware.org Subject: [binutils-gdb] Lack of bounds checking in vms-alpha.c parse_module X-Act-Checkin: binutils-gdb X-Git-Author: Alan Modra X-Git-Refname: refs/heads/master X-Git-Oldrev: b1f1cefd5844cb0ce10df78c6e1a8ed2e98faa77 X-Git-Newrev: 77c225bdeb410cf60da804879ad41622f5f1aa44 Message-Id: <20221212085939.4C84B395B066@sourceware.org> Date: Mon, 12 Dec 2022 08:59:39 +0000 (GMT) X-BeenThere: binutils-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 12 Dec 2022 08:59:39 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D77c225bdeb41= 0cf60da804879ad41622f5f1aa44 commit 77c225bdeb410cf60da804879ad41622f5f1aa44 Author: Alan Modra Date: Mon Dec 12 18:28:49 2022 +1030 Lack of bounds checking in vms-alpha.c parse_module =20 PR 29873 PR 29874 PR 29875 PR 29876 PR 29877 PR 29878 PR 29879 PR 29880 PR 29881 PR 29882 PR 29883 PR 29884 PR 29885 PR 29886 PR 29887 PR 29888 PR 29889 PR 29890 PR 29891 * vms-alpha.c (parse_module): Make length param bfd_size_type. Delete length =3D=3D -1 checks. Sanity check record_length. Sanity check DST__K_MODBEG, DST__K_RTNBEG, DST__K_RTNEND length= s. Sanity check DST__K_SOURCE and DST__K_LINE_NUM elements before accessing. (build_module_list): Pass dst_section size to parse_module. Diff: --- bfd/vms-alpha.c | 213 ++++++++++++++++++++++++++++++++++++++++++++--------= ---- 1 file changed, 168 insertions(+), 45 deletions(-) diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c index c0eb5bc5a2a..3b63259cc81 100644 --- a/bfd/vms-alpha.c +++ b/bfd/vms-alpha.c @@ -4345,7 +4345,7 @@ new_module (bfd *abfd) =20 static bool parse_module (bfd *abfd, struct module *module, unsigned char *ptr, - int length) + bfd_size_type length) { unsigned char *maxptr =3D ptr + length; unsigned char *src_ptr, *pcl_ptr; @@ -4366,7 +4366,7 @@ parse_module (bfd *abfd, struct module *module, unsig= ned char *ptr, return false; module->line_table =3D curr_line; =20 - while (length =3D=3D -1 || (ptr + 3) < maxptr) + while (ptr + 3 < maxptr) { /* The first byte is not counted in the recorded length. */ int rec_length =3D bfd_getl16 (ptr) + 1; @@ -4374,15 +4374,19 @@ parse_module (bfd *abfd, struct module *module, uns= igned char *ptr, =20 vms_debug2 ((2, "DST record: leng %d, type %d\n", rec_length, rec_ty= pe)); =20 - if (length =3D=3D -1 && rec_type =3D=3D DST__K_MODEND) + if (rec_length > maxptr - ptr) + break; + if (rec_type =3D=3D DST__K_MODEND) break; =20 switch (rec_type) { case DST__K_MODBEG: + if (rec_length <=3D DST_S_B_MODBEG_NAME) + break; module->name =3D _bfd_vms_save_counted_string (abfd, ptr + DST_S_B_MODBEG_NAME, - maxptr - (ptr + DST_S_B_MODBEG_NAME)); + rec_length - DST_S_B_MODBEG_NAME); =20 curr_pc =3D 0; prev_pc =3D 0; @@ -4396,13 +4400,15 @@ parse_module (bfd *abfd, struct module *module, uns= igned char *ptr, break; =20 case DST__K_RTNBEG: + if (rec_length <=3D DST_S_B_RTNBEG_NAME) + break; funcinfo =3D (struct funcinfo *) bfd_zalloc (abfd, sizeof (struct funcinfo)); if (!funcinfo) return false; funcinfo->name =3D _bfd_vms_save_counted_string (abfd, ptr + DST_S_B_RTNBEG_NAME, - maxptr - (ptr + DST_S_B_RTNBEG_NAME)); + rec_length - DST_S_B_RTNBEG_NAME); funcinfo->low =3D bfd_getl32 (ptr + DST_S_L_RTNBEG_ADDRESS); funcinfo->next =3D module->func_table; module->func_table =3D funcinfo; @@ -4412,6 +4418,8 @@ parse_module (bfd *abfd, struct module *module, unsig= ned char *ptr, break; =20 case DST__K_RTNEND: + if (rec_length < DST_S_L_RTNEND_SIZE + 4) + break; if (!module->func_table) return false; module->func_table->high =3D module->func_table->low @@ -4444,10 +4452,63 @@ parse_module (bfd *abfd, struct module *module, uns= igned char *ptr, =20 vms_debug2 ((3, "source info\n")); =20 - while (src_ptr < ptr + rec_length) + while (src_ptr - ptr < rec_length) { int cmd =3D src_ptr[0], cmd_length, data; =20 + switch (cmd) + { + case DST__K_SRC_DECLFILE: + if (src_ptr - ptr + DST_S_B_SRC_DF_LENGTH >=3D rec_length) + cmd_length =3D 0x10000; + else + cmd_length =3D src_ptr[DST_S_B_SRC_DF_LENGTH] + 2; + break; + + case DST__K_SRC_DEFLINES_B: + cmd_length =3D 2; + break; + + case DST__K_SRC_DEFLINES_W: + cmd_length =3D 3; + break; + + case DST__K_SRC_INCRLNUM_B: + cmd_length =3D 2; + break; + + case DST__K_SRC_SETFILE: + cmd_length =3D 3; + break; + + case DST__K_SRC_SETLNUM_L: + cmd_length =3D 5; + break; + + case DST__K_SRC_SETLNUM_W: + cmd_length =3D 3; + break; + + case DST__K_SRC_SETREC_L: + cmd_length =3D 5; + break; + + case DST__K_SRC_SETREC_W: + cmd_length =3D 3; + break; + + case DST__K_SRC_FORMFEED: + cmd_length =3D 1; + break; + + default: + cmd_length =3D 2; + break; + } + + if (src_ptr - ptr + cmd_length > rec_length) + break; + switch (cmd) { case DST__K_SRC_DECLFILE: @@ -4472,7 +4533,6 @@ parse_module (bfd *abfd, struct module *module, unsig= ned char *ptr, =20 module->file_table [fileid].name =3D filename; module->file_table [fileid].srec =3D 1; - cmd_length =3D src_ptr[DST_S_B_SRC_DF_LENGTH] + 2; vms_debug2 ((4, "DST_S_C_SRC_DECLFILE: %d, %s\n", fileid, module->file_table [fileid].name)); } @@ -4489,7 +4549,6 @@ parse_module (bfd *abfd, struct module *module, unsig= ned char *ptr, srec->sfile =3D curr_srec->sfile; curr_srec->next =3D srec; curr_srec =3D srec; - cmd_length =3D 2; vms_debug2 ((4, "DST_S_C_SRC_DEFLINES_B: %d\n", data)); break; =20 @@ -4504,14 +4563,12 @@ parse_module (bfd *abfd, struct module *module, uns= igned char *ptr, srec->sfile =3D curr_srec->sfile; curr_srec->next =3D srec; curr_srec =3D srec; - cmd_length =3D 3; vms_debug2 ((4, "DST_S_C_SRC_DEFLINES_W: %d\n", data)); break; =20 case DST__K_SRC_INCRLNUM_B: data =3D src_ptr[DST_S_B_SRC_UNSBYTE]; curr_srec->line +=3D data; - cmd_length =3D 2; vms_debug2 ((4, "DST_S_C_SRC_INCRLNUM_B: %d\n", data)); break; =20 @@ -4519,21 +4576,18 @@ parse_module (bfd *abfd, struct module *module, uns= igned char *ptr, data =3D bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD); curr_srec->sfile =3D data; curr_srec->srec =3D module->file_table[data].srec; - cmd_length =3D 3; vms_debug2 ((4, "DST_S_C_SRC_SETFILE: %d\n", data)); break; =20 case DST__K_SRC_SETLNUM_L: data =3D bfd_getl32 (src_ptr + DST_S_L_SRC_UNSLONG); curr_srec->line =3D data; - cmd_length =3D 5; vms_debug2 ((4, "DST_S_C_SRC_SETLNUM_L: %d\n", data)); break; =20 case DST__K_SRC_SETLNUM_W: data =3D bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD); curr_srec->line =3D data; - cmd_length =3D 3; vms_debug2 ((4, "DST_S_C_SRC_SETLNUM_W: %d\n", data)); break; =20 @@ -4541,7 +4595,6 @@ parse_module (bfd *abfd, struct module *module, unsig= ned char *ptr, data =3D bfd_getl32 (src_ptr + DST_S_L_SRC_UNSLONG); curr_srec->srec =3D data; module->file_table[curr_srec->sfile].srec =3D data; - cmd_length =3D 5; vms_debug2 ((4, "DST_S_C_SRC_SETREC_L: %d\n", data)); break; =20 @@ -4549,19 +4602,16 @@ parse_module (bfd *abfd, struct module *module, uns= igned char *ptr, data =3D bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD); curr_srec->srec =3D data; module->file_table[curr_srec->sfile].srec =3D data; - cmd_length =3D 3; vms_debug2 ((4, "DST_S_C_SRC_SETREC_W: %d\n", data)); break; =20 case DST__K_SRC_FORMFEED: - cmd_length =3D 1; vms_debug2 ((4, "DST_S_C_SRC_FORMFEED\n")); break; =20 default: _bfd_error_handler (_("unknown source command %d"), cmd); - cmd_length =3D 2; break; } =20 @@ -4574,18 +4624,114 @@ parse_module (bfd *abfd, struct module *module, un= signed char *ptr, =20 vms_debug2 ((3, "line info\n")); =20 - while (pcl_ptr < ptr + rec_length) + while (pcl_ptr - ptr < rec_length) { /* The command byte is signed so we must sign-extend it. */ int cmd =3D ((signed char *)pcl_ptr)[0], cmd_length, data; =20 + switch (cmd) + { + case DST__K_DELTA_PC_W: + cmd_length =3D 3; + break; + + case DST__K_DELTA_PC_L: + cmd_length =3D 5; + break; + + case DST__K_INCR_LINUM: + cmd_length =3D 2; + break; + + case DST__K_INCR_LINUM_W: + cmd_length =3D 3; + break; + + case DST__K_INCR_LINUM_L: + cmd_length =3D 5; + break; + + case DST__K_SET_LINUM_INCR: + cmd_length =3D 2; + break; + + case DST__K_SET_LINUM_INCR_W: + cmd_length =3D 3; + break; + + case DST__K_RESET_LINUM_INCR: + cmd_length =3D 1; + break; + + case DST__K_BEG_STMT_MODE: + cmd_length =3D 1; + break; + + case DST__K_END_STMT_MODE: + cmd_length =3D 1; + break; + + case DST__K_SET_LINUM_B: + cmd_length =3D 2; + break; + + case DST__K_SET_LINUM: + cmd_length =3D 3; + break; + + case DST__K_SET_LINUM_L: + cmd_length =3D 5; + break; + + case DST__K_SET_PC: + cmd_length =3D 2; + break; + + case DST__K_SET_PC_W: + cmd_length =3D 3; + break; + + case DST__K_SET_PC_L: + cmd_length =3D 5; + break; + + case DST__K_SET_STMTNUM: + cmd_length =3D 2; + break; + + case DST__K_TERM: + cmd_length =3D 2; + break; + + case DST__K_TERM_W: + cmd_length =3D 3; + break; + + case DST__K_TERM_L: + cmd_length =3D 5; + break; + + case DST__K_SET_ABS_PC: + cmd_length =3D 5; + break; + + default: + if (cmd <=3D 0) + cmd_length =3D 1; + else + cmd_length =3D 2; + break; + } + + if (pcl_ptr - ptr + cmd_length > rec_length) + break; + switch (cmd) { case DST__K_DELTA_PC_W: data =3D bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD); curr_pc +=3D data; curr_linenum +=3D 1; - cmd_length =3D 3; vms_debug2 ((4, "DST__K_DELTA_PC_W: %d\n", data)); break; =20 @@ -4593,131 +4739,111 @@ parse_module (bfd *abfd, struct module *module, u= nsigned char *ptr, data =3D bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); curr_pc +=3D data; curr_linenum +=3D 1; - cmd_length =3D 5; vms_debug2 ((4, "DST__K_DELTA_PC_L: %d\n", data)); break; =20 case DST__K_INCR_LINUM: data =3D pcl_ptr[DST_S_B_PCLINE_UNSBYTE]; curr_linenum +=3D data; - cmd_length =3D 2; vms_debug2 ((4, "DST__K_INCR_LINUM: %d\n", data)); break; =20 case DST__K_INCR_LINUM_W: data =3D bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD); curr_linenum +=3D data; - cmd_length =3D 3; vms_debug2 ((4, "DST__K_INCR_LINUM_W: %d\n", data)); break; =20 case DST__K_INCR_LINUM_L: data =3D bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); curr_linenum +=3D data; - cmd_length =3D 5; vms_debug2 ((4, "DST__K_INCR_LINUM_L: %d\n", data)); break; =20 case DST__K_SET_LINUM_INCR: _bfd_error_handler (_("%s not implemented"), "DST__K_SET_LINUM_INCR"); - cmd_length =3D 2; break; =20 case DST__K_SET_LINUM_INCR_W: _bfd_error_handler (_("%s not implemented"), "DST__K_SET_LINUM_INCR_W"); - cmd_length =3D 3; break; =20 case DST__K_RESET_LINUM_INCR: _bfd_error_handler (_("%s not implemented"), "DST__K_RESET_LINUM_INCR"); - cmd_length =3D 1; break; =20 case DST__K_BEG_STMT_MODE: _bfd_error_handler (_("%s not implemented"), "DST__K_BEG_STMT_MODE"); - cmd_length =3D 1; break; =20 case DST__K_END_STMT_MODE: _bfd_error_handler (_("%s not implemented"), "DST__K_END_STMT_MODE"); - cmd_length =3D 1; break; =20 case DST__K_SET_LINUM_B: data =3D pcl_ptr[DST_S_B_PCLINE_UNSBYTE]; curr_linenum =3D data; - cmd_length =3D 2; vms_debug2 ((4, "DST__K_SET_LINUM_B: %d\n", data)); break; =20 case DST__K_SET_LINUM: data =3D bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD); curr_linenum =3D data; - cmd_length =3D 3; vms_debug2 ((4, "DST__K_SET_LINE_NUM: %d\n", data)); break; =20 case DST__K_SET_LINUM_L: data =3D bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); curr_linenum =3D data; - cmd_length =3D 5; vms_debug2 ((4, "DST__K_SET_LINUM_L: %d\n", data)); break; =20 case DST__K_SET_PC: _bfd_error_handler (_("%s not implemented"), "DST__K_SET_PC"); - cmd_length =3D 2; break; =20 case DST__K_SET_PC_W: _bfd_error_handler (_("%s not implemented"), "DST__K_SET_PC_W"); - cmd_length =3D 3; break; =20 case DST__K_SET_PC_L: _bfd_error_handler (_("%s not implemented"), "DST__K_SET_PC_L"); - cmd_length =3D 5; break; =20 case DST__K_SET_STMTNUM: _bfd_error_handler (_("%s not implemented"), "DST__K_SET_STMTNUM"); - cmd_length =3D 2; break; =20 case DST__K_TERM: data =3D pcl_ptr[DST_S_B_PCLINE_UNSBYTE]; curr_pc +=3D data; - cmd_length =3D 2; vms_debug2 ((4, "DST__K_TERM: %d\n", data)); break; =20 case DST__K_TERM_W: data =3D bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD); curr_pc +=3D data; - cmd_length =3D 3; vms_debug2 ((4, "DST__K_TERM_W: %d\n", data)); break; =20 case DST__K_TERM_L: data =3D bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); curr_pc +=3D data; - cmd_length =3D 5; vms_debug2 ((4, "DST__K_TERM_L: %d\n", data)); break; =20 case DST__K_SET_ABS_PC: data =3D bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); curr_pc =3D data; - cmd_length =3D 5; vms_debug2 ((4, "DST__K_SET_ABS_PC: 0x%x\n", data)); break; =20 @@ -4726,15 +4852,11 @@ parse_module (bfd *abfd, struct module *module, uns= igned char *ptr, { curr_pc -=3D cmd; curr_linenum +=3D 1; - cmd_length =3D 1; vms_debug2 ((4, "bump pc to 0x%lx and line to %d\n", (unsigned long)curr_pc, curr_linenum)); } else - { - _bfd_error_handler (_("unknown line command %d"), cmd); - cmd_length =3D 2; - } + _bfd_error_handler (_("unknown line command %d"), cmd); break; } =20 @@ -4864,7 +4986,8 @@ build_module_list (bfd *abfd) return NULL; =20 module =3D new_module (abfd); - if (!parse_module (abfd, module, PRIV (dst_section)->contents, -1)) + if (!parse_module (abfd, module, PRIV (dst_section)->contents, + PRIV (dst_section)->size)) return NULL; list =3D module; }