Skip to content

Commit

Permalink
[#964] Fix SIG-11 in trigger_parse.c when $ZTRIGGER has incomplete -x…
Browse files Browse the repository at this point in the history
…ecute string

Background
----------
* Below is pasted from https://gitlab.com/YottaDB/DB/YDB/-/issues/964#note_1267098363

* The below SIG-11 in `trigger_parse.c` happens in YottaDB and GT.M. In Release and Debug builds.

  ```m
  YDB>if $ztrigger("item","+","PAGFIbal(1) -commands=S -xecute=""")
  %YDB-F-KILLBYSIGSINFO1, YottaDB process 28864 has been killed by a signal 11 at address 0x00007FA4E345D3E0 (vaddr 0x00000000 00000000)
  %YDB-F-SIGMAPERR, Signal was caused by an address not mapped to an object
  ```

  ```c
  #7  trigger_parse (input=0x0, input_len=0, trigvn=0x7ffe6146bcc0 "", values=0x7ffe6146be70, value_len=0x7ffe6146bd90, max_len=0x7ffe6146bbdc, multi_line_xecute=0x7ffe6146bbd4) at sr_unix/trigger_parse.c:1368
  #8  trigger_update_rec (trigger_rec=0x7fa4e38e62a8, noprompt=1, trig_stats=0x7ffe61480bf0, trigfile_device=0x0, record_num=0x0) at sr_unix/trigger_update.c:1417
  #9  trigger_update_rec_helper.constprop.0 (trigger_rec=trigger_rec@entry=0x7fa4e38e62a8, trig_stats=trig_stats@entry=0x7ffe61480bf0, noprompt=1) at sr_unix/trigger_update.c:2217
  #10 trigger_update (trigger_rec=0x7fa4e38e62a8) at sr_unix/trigger_update.c:2270
  #11 op_fnztrigger (func=<optimized out>, arg1=0x7fa4e38e62a8, arg2=<optimized out>, dst=0x55e1696279e0) at sr_port/op_fnztrigger.c:248

  (gdb) f 7
  #7  trigger_parse (input=0x0, input_len=0, trigvn=0x7ffe6146bcc0 "", values=0x7ffe6146be70, value_len=0x7ffe6146bd90, max_len=0x7ffe6146bbdc, multi_line_xecute=0x7ffe6146bbd4) at sr_unix/trigger_parse.c:1368
  1368            if ('^' != *ptr1++)

  (gdb) p ptr1
  $1 = 0x1 <error: Cannot access memory at address 0x1>
  ```

Issue
-----
* The function `trigger_parse()` is presented with an input buffer `input` and a length `input_len`.
  But while processing the input buffer, it does not ensure all references are within the buffer limits.
  This means that if `-xecute=` specification is incomplete (in the example above, the string starts
  with a double-quote but ends abruptly without an ending double-quote), we could enter this function
  with an `input_len` value of 0. In that case, we would try to access the very first byte resulting
  in a SIG-11.

Fix
---
* The fix to the above issue is to check if `input_len` is 0 and if so return right away with an error
  from the `trigger_parse()` function.

* But while examining this function, I realized similar issues existed in various other error code paths.
  All of them scanned past the input buffer (for a global nam, subscripts etc.) without honoring the
  input buffer bounds.

* So all these issues are now fixed in this commit by introducing a new variable `ptr1_top` which is set
  to the end of the valid input buffer and every access of the input buffer (mostly done through the
  variable `*ptr1`) is validated to be within bounds by comparing it against `ptr1_top` and if not an
  error is issued. This is done by adding `||` conditions involving `ptr1_top` to pre-existing error
  code paths.
  • Loading branch information
nars1 committed Feb 6, 2023
1 parent 01ec268 commit a4d4a33
Showing 1 changed file with 9 additions and 7 deletions.
16 changes: 9 additions & 7 deletions sr_unix/trigger_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Copyright (c) 2010-2020 Fidelity National Information *
* Services, Inc. and/or its subsidiaries. All rights reserved. *
* *
* Copyright (c) 2018-2022 YottaDB LLC and/or its subsidiaries. *
* Copyright (c) 2018-2023 YottaDB LLC and/or its subsidiaries. *
* All rights reserved. *
* *
* This source code contains the intellectual property *
Expand Down Expand Up @@ -1316,7 +1316,7 @@ boolean_t trigger_parse(char *input, uint4 input_len, char *trigvn, char **value
int parse_ret;
boolean_t delim_present, name_present, pieces_present, xecute_present, zdelim_present;
char *ptr;
char *ptr1;
char *ptr1, *ptr1_top;
char *ptr2;
int4 rec_num;
CLI_ENTRY *save_cmd_ary;
Expand Down Expand Up @@ -1364,21 +1364,23 @@ boolean_t trigger_parse(char *input, uint4 input_len, char *trigvn, char **value
return TRIG_SUCCESS;
}
ptr1 = input;
assert(0 <= input_len);
len = (uint4)input_len;
if ('^' != *ptr1++)
ptr1_top = ptr1 + len;
if ((ptr1 >= ptr1_top) || ('^' != *ptr1++))
{
ERROR_MSG_RETURN("Error : Missing global name:\n", input_len, input);
}
ptr = ptr1;
len--;
if (('%' != *ptr1) && !ISALPHA_ASCII(*ptr1))
if ((ptr1 >= ptr1_top) || (('%' != *ptr1) && !ISALPHA_ASCII(*ptr1)))
{
ERROR_MSG_RETURN("Error : Invalid global name:\n", input_len, input);
}
ptr1++;
while (ISALNUM_ASCII(*ptr1))
while ((ptr1 < ptr1_top) && ISALNUM_ASCII(*ptr1))
ptr1++;
if (('(' != *ptr1) && !ISSPACE_ASCII(*ptr1))
if ((ptr1 > ptr1_top) || (('(' != *ptr1) && !ISSPACE_ASCII(*ptr1)))
{
ERROR_MSG_RETURN("Error : Invalid global name:\n", input_len, input);
}
Expand All @@ -1400,7 +1402,7 @@ boolean_t trigger_parse(char *input, uint4 input_len, char *trigvn, char **value
/* lookup global to get collation info */
len -= (uint4)trigvn_len;
ptr2 = ptr1;
if ('(' == *ptr1)
if ((ptr1 < ptr1_top) && ('(' == *ptr1))
{
ptr1++;
len--;
Expand Down

0 comments on commit a4d4a33

Please sign in to comment.