poke-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [RFC][PATCH] pkl, testsuite: Improve detection of overflow in intege


From: Mohammad-Reza Nabipoor
Subject: Re: [RFC][PATCH] pkl, testsuite: Improve detection of overflow in integer literals
Date: Sat, 24 Sep 2022 10:10:30 +0330

ping

On Mon, Aug 08, 2022 at 03:20:26AM +0430, Mohammad-Reza Nabipoor wrote:
> With this commit the following integer literals are invalid:
> 
>   8N, 128B, 32768H, 2147483648, 9223372036854775808L
> 
> But to keep -8N, -128B, -32768H, -2147483648, -9223372036854775808L
> valid literals, we have to consider minus sign as part of the integer
> literal.  As a consequence, `1-2' is no longer a valid expression.
> Instead, one has to write `1- 2'.
> 
> 2022-08-08  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>
> 
>       * libpoke/pkl-lex.l (pkl_lex_get_base): Add new param `negative_p'.
>       (integer_literal_overflow_p): New function for overflow check.
>       (Alien token rule): Use `integer_literal_overflow_p'.
>       (Offset literal rule): Adapt `pkl_lex_get_base' invocation.
>       (Integer literal rule): Add optional sign recognition at the
>       beginning and update integer literal overflow detection logic.
>       * testsuite/poke.pkl/array-integ-33.pk: Adapt to new semantics.
>       * testsuite/poke.pkl/arrays-diag-3.pk: Likewise.
>       * testsuite/poke.pkl/cdiv-integers-overflow-1.pk: Likewise.
>       * testsuite/poke.pkl/cdiv-integers-overflow-diag-2.pk: Likewise.
>       * testsuite/poke.pkl/div-integers-overflow-1.pk: Likewise.
>       * testsuite/poke.pkl/div-integers-overflow-diag-2.pk: Likewise.
>       * testsuite/poke.pkl/getenv-1.pk: Likewise.
>       * testsuite/poke.pkl/mod-integers-overflow-1.pk: Likewise.
>       * testsuite/poke.pkl/mod-integers-overflow-diag-2.pk: Likewise.
>       * testsuite/poke.pkl/neg-int-overflow-1.pk: Likewise.
>       * testsuite/poke.pkl/neg-int-overflow-diag-1.pk: Likewise.
>       * testsuite/poke.pkl/promo-array-arg-4.pk: Likewise.
>       * testsuite/poke.pkl/promo-array-arg-5.pk: Likewise.
>       * testsuite/poke.pkl/promo-array-return-5.pk: Likewise.
>       * testsuite/poke.pkl/sub-integers-overflow-1.pk: Likewise.
> ---
> 
> Hello Jose.
> 
> With this patch, nobody can write nonsenses like 666B, but OTOH we
> have to force people (including you :D) to put spaces around the binary
> minus operator.
> 
> Is this a good trade-off?
> 
> 
> Regards,
> Mohammad-Reza
> 
> 
>  ChangeLog                                     |  24 ++++
>  libpoke/pkl-lex.l                             | 120 +++++++++---------
>  testsuite/poke.pkl/array-integ-33.pk          |   4 +-
>  testsuite/poke.pkl/arrays-diag-3.pk           |   2 +-
>  .../poke.pkl/cdiv-integers-overflow-1.pk      |   2 +-
>  .../poke.pkl/cdiv-integers-overflow-diag-2.pk |   2 +-
>  testsuite/poke.pkl/div-integers-overflow-1.pk |   2 +-
>  .../poke.pkl/div-integers-overflow-diag-2.pk  |   2 +-
>  testsuite/poke.pkl/getenv-1.pk                |   2 +-
>  testsuite/poke.pkl/mod-integers-overflow-1.pk |   2 +-
>  .../poke.pkl/mod-integers-overflow-diag-2.pk  |   2 +-
>  testsuite/poke.pkl/neg-int-overflow-1.pk      |   2 +-
>  testsuite/poke.pkl/neg-int-overflow-diag-1.pk |   2 +-
>  testsuite/poke.pkl/promo-array-arg-4.pk       |   4 +-
>  testsuite/poke.pkl/promo-array-arg-5.pk       |   4 +-
>  testsuite/poke.pkl/promo-array-return-5.pk    |   4 +-
>  testsuite/poke.pkl/sub-integers-overflow-1.pk |   2 +-
>  17 files changed, 103 insertions(+), 79 deletions(-)
> 
> diff --git a/ChangeLog b/ChangeLog
> index ef9187f5..85a97378 100644
> --- a/ChangeLog
> +++ b/ChangeLog
> @@ -1,3 +1,27 @@
> +2022-08-08  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>
> +
> +     * libpoke/pkl-lex.l (pkl_lex_get_base): Add new param `negative_p'.
> +     (integer_literal_overflow_p): New function for overflow check.
> +     (Alien token rule): Use `integer_literal_overflow_p'.
> +     (Offset literal rule): Adapt `pkl_lex_get_base' invocation.
> +     (Integer literal rule): Add optional sign recognition at the
> +     beginning and update integer literal overflow detection logic.
> +     * testsuite/poke.pkl/array-integ-33.pk: Adapt to new semantics.
> +     * testsuite/poke.pkl/arrays-diag-3.pk: Likewise.
> +     * testsuite/poke.pkl/cdiv-integers-overflow-1.pk: Likewise.
> +     * testsuite/poke.pkl/cdiv-integers-overflow-diag-2.pk: Likewise.
> +     * testsuite/poke.pkl/div-integers-overflow-1.pk: Likewise.
> +     * testsuite/poke.pkl/div-integers-overflow-diag-2.pk: Likewise.
> +     * testsuite/poke.pkl/getenv-1.pk: Likewise.
> +     * testsuite/poke.pkl/mod-integers-overflow-1.pk: Likewise.
> +     * testsuite/poke.pkl/mod-integers-overflow-diag-2.pk: Likewise.
> +     * testsuite/poke.pkl/neg-int-overflow-1.pk: Likewise.
> +     * testsuite/poke.pkl/neg-int-overflow-diag-1.pk: Likewise.
> +     * testsuite/poke.pkl/promo-array-arg-4.pk: Likewise.
> +     * testsuite/poke.pkl/promo-array-arg-5.pk: Likewise.
> +     * testsuite/poke.pkl/promo-array-return-5.pk: Likewise.
> +     * testsuite/poke.pkl/sub-integers-overflow-1.pk: Likewise.
> +
>  2022-07-25  Jose E. Marchesi  <jemarch@gnu.org>
>  
>       * configure.ac: Bump version to 2.4.
> diff --git a/libpoke/pkl-lex.l b/libpoke/pkl-lex.l
> index 78f1ce1d..583b21be 100644
> --- a/libpoke/pkl-lex.l
> +++ b/libpoke/pkl-lex.l
> @@ -101,14 +101,16 @@
>  
>  /* Note that the following function assumes that STR is a pointer of a
>     string that satisfies the regexp
> -   ({HEXCST}|{BINCST}|{OCTCST}|{DECCST}) */
> +   "-"?({HEXCST}|{BINCST}|{OCTCST}|{DECCST}) */
>  
>  int
> -pkl_lex_get_base  (const char *str, int *offset)
> +pkl_lex_get_base  (const char *str, int *offset, int *negative_p)
>  {
>   int base = 10;
>   *offset = 0;
>  
> + if ((*negative_p = str[0] == '-'))
> +   str++;
>   if (str[0] == '0')
>    {
>      if (str[1] == 'x' || str[1] == 'X')
> @@ -128,7 +130,51 @@ pkl_lex_get_base  (const char *str, int *offset)
>      }
>    }
>  
> - return base;
> +  *offset += *negative_p;
> +  return base;
> +}
> +
> +static int
> +integer_literal_overflow_p (uint64_t value, int signed_p, int negative_p,
> +                            int *width)
> +{
> +  /* If the width is not already known (e.g., based on the suffix),
> +     the type of the integer constant is the smallest signed or unsigned
> +     integer capable of holding it, starting with 32 bits, in steps of
> +     power of two and up to 64 bits.  But note these are positive values!  */
> +
> +  if (*width == 0)
> +    {
> +      if (value > 0x0000000080000000 && value <= 0x00000000ffffffff)
> +        *width = signed_p ? 64 : 32;
> +      else if (value & 0xffffffff00000000)
> +        *width = 64;
> +      else
> +        *width = 32;
> +    }
> +
> +  if (*width != 64)
> +    {
> +      uint64_t mask = 1;
> +
> +      mask <<= *width;
> +      mask -= 1;
> +      if (value & ~mask)
> +        return 1;
> +    }
> +
> +  /* Handle overflow in signed integers.  */
> +  if (signed_p)
> +    {
> +      uint64_t limit = (uint64_t)1 << (*width - 1);
> +
> +      if (negative_p && value > limit)
> +        return 1;
> +      if (!negative_p && value >= limit)
> +        return 1;
> +    }
> +
> +  return 0;
>  }
>  
>  %}
> @@ -438,23 +484,8 @@ S ::
>              int width = token->value.integer.width;
>              pkl_ast_node type;
>  
> -            /* As with regular integer tokens, the type of the integer
> -               constant is the smallest signed or unsigned integer
> -               capable of holding it, starting with 32 bits, in steps
> -               of power of two and up to 64 bits. */
> -
> -            if (width == 0)
> -              {
> -                if (value > 0x0000000080000000 && value <= 
> 0x00000000ffffffff)
> -                  width = signed_p ? 64 : 32;
> -                else if (value & 0xffffffff00000000)
> -                  width = 64;
> -                else
> -                  width = 32;
> -              }
> -
> -            /* Handle overflow in signed integers. */
> -            if (signed_p && value >= 0x8000000000000000)
> +            if (integer_literal_overflow_p (value, signed_p,
> +                                            /*negative_p (dummy)*/ 1, 
> &width))
>                return INTEGER_OVERFLOW;
>  
>              type = pkl_ast_make_integral_type (yyextra->ast, width, 
> signed_p);
> @@ -472,23 +503,8 @@ S ::
>              int width = token->value.offset.width;
>              pkl_ast_node unit, magnitude, magnitude_type, offset_type, 
> unit_type;
>  
> -            /* As with regular integer tokens, the type of the integer
> -               constant is the smallest signed or unsigned integer
> -               capable of holding it, starting with 32 bits, in steps
> -               of power of two and up to 64 bits. */
> -
> -            if (width == 0)
> -              {
> -                if (value > 0x0000000080000000 && value <= 
> 0x00000000ffffffff)
> -                  width = signed_p ? 64 : 32;
> -                else if (value & 0xffffffff00000000)
> -                  width = 64;
> -                else
> -                  width = 32;
> -              }
> -
> -            /* Handle overflow in signed integers. */
> -            if (signed_p && value >= 0x8000000000000000)
> +            if (integer_literal_overflow_p (value, signed_p,
> +                                            /*negative_p (dummy)*/ 1, 
> &width))
>                return INTEGER_OVERFLOW;
>  
>              /* Build the offset magnitude.  */
> @@ -530,12 +546,12 @@ S ::
>  
>  #({HEXCST}|{BINCST}|{OCTCST}|{DECCST}) {
>    char *end;
> -  int base, offset;
> +  int base, offset, negative_p;
>    uint64_t value;
>    pkl_ast_node type
>       = pkl_ast_make_integral_type (yyextra->ast, 64, 0);
>  
> -  base = pkl_lex_get_base (yytext + 1, &offset);
> +  base = pkl_lex_get_base (yytext + 1, &offset, &negative_p);
>    value = strtoll (yytext + 1 + offset, &end, base);
>    yylval->ast = pkl_ast_make_integer (yyextra->ast, value);
>    PKL_AST_TYPE (yylval->ast) = ASTREF (type);
> @@ -577,9 +593,9 @@ S ::
>       return IDENTIFIER;
>  }
>  
> -({HEXCST}|{BINCST}|{OCTCST}|{DECCST}){IS}? {
> +"-"?({HEXCST}|{BINCST}|{OCTCST}|{DECCST}){IS}? {
>    uint64_t value;
> -  int base, offset, signed_p, width;
> +  int base, offset, signed_p, width, negative_p;
>    char *p, *end;
>    pkl_ast_node type;
>  
> @@ -593,7 +609,7 @@ S ::
>         *tmp = *(tmp + 1);
>    }
>  
> -  base = pkl_lex_get_base (yytext, &offset);
> +  base = pkl_lex_get_base (yytext, &offset, &negative_p);
>  
>    /* strtoull can fail here only in case of overflow.  */
>    errno = 0;
> @@ -619,28 +635,12 @@ S ::
>        || ((*end != '\0') && ((*(end + 1) == 'n' || *(end + 1) == 'N'))))
>      width = 4;
>  
> -  /* If not specified with the 'l' or 'L' suffix, the type of the
> -     integer constant is the smallest signed or unsigned integer
> -     capable of holding it, starting with 32 bits, in steps of power
> -     of two and up to 64 bits.  But note these are positive values! */
> -
> -  if (width == 0)
> -  {
> -    if (value > 0x0000000080000000 && value <= 0x00000000ffffffff)
> -      width = signed_p ? 64 : 32;
> -    else if (value & 0xffffffff00000000)
> -      width = 64;
> -    else
> -      width = 32;
> -  }
> -
> -  /* Handle overflow in signed integers. */
> -  if (signed_p && value >= 0x8000000000000000)
> +  if (integer_literal_overflow_p (value, signed_p, negative_p, &width))
>      return INTEGER_OVERFLOW;
>  
>    type = pkl_ast_make_integral_type (yyextra->ast, width, signed_p);
>  
> -  yylval->ast = pkl_ast_make_integer (yyextra->ast, value);
> +  yylval->ast = pkl_ast_make_integer (yyextra->ast, negative_p ? -value : 
> value);
>    PKL_AST_TYPE (yylval->ast) = ASTREF (type);
>  
>    return INTEGER;
> diff --git a/testsuite/poke.pkl/array-integ-33.pk 
> b/testsuite/poke.pkl/array-integ-33.pk
> index 3db905ea..6481063c 100644
> --- a/testsuite/poke.pkl/array-integ-33.pk
> +++ b/testsuite/poke.pkl/array-integ-33.pk
> @@ -1,9 +1,9 @@
>  /* { dg-do run } */
>  
> -var a = [[[[[[[[0xdeadH,0xbeefH]]]]]]]];
> +var a = [[[[[[[[0xdeadUH,0xbeefUH]]]]]]]];
>  
>  /* { dg-command {.set obase 16} } */
>  /* { dg-command {a as int<32>} } */
>  /* { dg-output {0xdeadbeef\n} } */
> -/* { dg-command {[[[[[[[[0xdeadH,0xbeefH]]]]]]]] as int<32>} } */
> +/* { dg-command {[[[[[[[[0xdeadUH,0xbeefUH]]]]]]]] as int<32>} } */
>  /* { dg-output {0xdeadbeef} } */
> diff --git a/testsuite/poke.pkl/arrays-diag-3.pk 
> b/testsuite/poke.pkl/arrays-diag-3.pk
> index 8e16b95b..90d5adc1 100644
> --- a/testsuite/poke.pkl/arrays-diag-3.pk
> +++ b/testsuite/poke.pkl/arrays-diag-3.pk
> @@ -1,3 +1,3 @@
>  /* { dg-do compile } */
>  
> -var a = [0,1,.[1-2]=10]; /* { dg-error "negative" } */
> +var a = [0,1,.[1 - 2]=10]; /* { dg-error "negative" } */
> diff --git a/testsuite/poke.pkl/cdiv-integers-overflow-1.pk 
> b/testsuite/poke.pkl/cdiv-integers-overflow-1.pk
> index 327db6b0..44b1b8bc 100644
> --- a/testsuite/poke.pkl/cdiv-integers-overflow-1.pk
> +++ b/testsuite/poke.pkl/cdiv-integers-overflow-1.pk
> @@ -1,6 +1,6 @@
>  /* { dg-do run } */
>  
> -var x = 0x8000_0000;
> +var x = -0x8000_0000;
>  
>  /* { dg-command {  try x /^ -1; catch if E_overflow { print "caught\n"; } } 
> } */
>  /* { dg-output "caught" } */
> diff --git a/testsuite/poke.pkl/cdiv-integers-overflow-diag-2.pk 
> b/testsuite/poke.pkl/cdiv-integers-overflow-diag-2.pk
> index d2e2472e..d4060568 100644
> --- a/testsuite/poke.pkl/cdiv-integers-overflow-diag-2.pk
> +++ b/testsuite/poke.pkl/cdiv-integers-overflow-diag-2.pk
> @@ -1,4 +1,4 @@
>  /* { dg-do compile } */
>  
>  var res
> -  = 0x8000_0000 /^ -1; /* { dg-error "overflow" } */
> +  = -0x8000_0000 /^ -1; /* { dg-error "overflow" } */
> diff --git a/testsuite/poke.pkl/div-integers-overflow-1.pk 
> b/testsuite/poke.pkl/div-integers-overflow-1.pk
> index 23fc279c..ba051e6a 100644
> --- a/testsuite/poke.pkl/div-integers-overflow-1.pk
> +++ b/testsuite/poke.pkl/div-integers-overflow-1.pk
> @@ -1,6 +1,6 @@
>  /* { dg-do run } */
>  
> -var x = 0x8000_0000;
> +var x = -0x8000_0000;
>  
>  /* { dg-command {  try x / -1; catch if E_overflow { print "caught\n"; } } } 
> */
>  /* { dg-output "caught" } */
> diff --git a/testsuite/poke.pkl/div-integers-overflow-diag-2.pk 
> b/testsuite/poke.pkl/div-integers-overflow-diag-2.pk
> index e530daa8..50397b95 100644
> --- a/testsuite/poke.pkl/div-integers-overflow-diag-2.pk
> +++ b/testsuite/poke.pkl/div-integers-overflow-diag-2.pk
> @@ -1,4 +1,4 @@
>  /* { dg-do compile } */
>  
>  var res
> -  = 0x8000_0000 / -1; /* { dg-error "overflow" } */
> +  = -0x8000_0000 / -1; /* { dg-error "overflow" } */
> diff --git a/testsuite/poke.pkl/getenv-1.pk b/testsuite/poke.pkl/getenv-1.pk
> index 4c81f209..13d3de72 100644
> --- a/testsuite/poke.pkl/getenv-1.pk
> +++ b/testsuite/poke.pkl/getenv-1.pk
> @@ -6,5 +6,5 @@
>  var picklesdir = getenv ("POKEPICKLESDIR");
>  var length = picklesdir'length;
>  
> -/* { dg-command { picklesdir[length-8:length] } } */
> +/* { dg-command { picklesdir[length - 8:length] } } */
>  /* { dg-output {"/pickles"} } */
> diff --git a/testsuite/poke.pkl/mod-integers-overflow-1.pk 
> b/testsuite/poke.pkl/mod-integers-overflow-1.pk
> index 9452b5d6..bcdf53b5 100644
> --- a/testsuite/poke.pkl/mod-integers-overflow-1.pk
> +++ b/testsuite/poke.pkl/mod-integers-overflow-1.pk
> @@ -1,6 +1,6 @@
>  /* { dg-do run } */
>  
> -var x = 0x8000_0000;
> +var x = -0x8000_0000;
>  
>  /* { dg-command {  try x % -1; catch if E_overflow { print "caught\n"; } } } 
> */
>  /* { dg-output "caught" } */
> diff --git a/testsuite/poke.pkl/mod-integers-overflow-diag-2.pk 
> b/testsuite/poke.pkl/mod-integers-overflow-diag-2.pk
> index 15277be3..0ebd9c91 100644
> --- a/testsuite/poke.pkl/mod-integers-overflow-diag-2.pk
> +++ b/testsuite/poke.pkl/mod-integers-overflow-diag-2.pk
> @@ -1,4 +1,4 @@
>  /* { dg-do compile } */
>  
>  var res
> -  = 0x8000_0000 % -1; /* { dg-error "overflow" } */
> +  = -0x8000_0000 % -1; /* { dg-error "overflow" } */
> diff --git a/testsuite/poke.pkl/neg-int-overflow-1.pk 
> b/testsuite/poke.pkl/neg-int-overflow-1.pk
> index 52fad876..8d769b61 100644
> --- a/testsuite/poke.pkl/neg-int-overflow-1.pk
> +++ b/testsuite/poke.pkl/neg-int-overflow-1.pk
> @@ -1,6 +1,6 @@
>  /* { dg-do run } */
>  
> -var x = 0x8000_0000;
> +var x = -0x8000_0000;
>  
>  /* { dg-command {  try -x; catch if E_overflow { print "caught\n"; } } } */
>  /* { dg-output "caught" } */
> diff --git a/testsuite/poke.pkl/neg-int-overflow-diag-1.pk 
> b/testsuite/poke.pkl/neg-int-overflow-diag-1.pk
> index 8e152221..76074eab 100644
> --- a/testsuite/poke.pkl/neg-int-overflow-diag-1.pk
> +++ b/testsuite/poke.pkl/neg-int-overflow-diag-1.pk
> @@ -1,4 +1,4 @@
>  /* { dg-do compile } */
>  
>  var res
> -  = -0x8000_0000; /* { dg-error "overflow" } */
> +  = 0 - -0x8000_0000; /* { dg-error "overflow" } */
> diff --git a/testsuite/poke.pkl/promo-array-arg-4.pk 
> b/testsuite/poke.pkl/promo-array-arg-4.pk
> index 23b8eeda..94dc2b85 100644
> --- a/testsuite/poke.pkl/promo-array-arg-4.pk
> +++ b/testsuite/poke.pkl/promo-array-arg-4.pk
> @@ -1,8 +1,8 @@
>  /* { dg-do run } */
>  
>  var x = 3;
> -fun foo = (int[x-1] a) int: { return a[1]; }
> -fun bar = (int[x-1][x-1] a) int: { return a[1][1]; }
> +fun foo = (int[x - 1] a) int: { return a[1]; }
> +fun bar = (int[x - 1][x - 1] a) int: { return a[1][1]; }
>  
>  /* { dg-command { foo ([1,2]) } } */
>  /* { dg-output "2" } */
> diff --git a/testsuite/poke.pkl/promo-array-arg-5.pk 
> b/testsuite/poke.pkl/promo-array-arg-5.pk
> index a4864328..1f29de4f 100644
> --- a/testsuite/poke.pkl/promo-array-arg-5.pk
> +++ b/testsuite/poke.pkl/promo-array-arg-5.pk
> @@ -1,8 +1,8 @@
>  /* { dg-do run } */
>  
>  var x = 3;
> -fun foo = (int[x-1] a) int: { return a[1]; }
> -fun bar = (int[x-1][x-1] a) int: { return a[1][1]; }
> +fun foo = (int[x - 1] a) int: { return a[1]; }
> +fun bar = (int[x - 1][x - 1] a) int: { return a[1][1]; }
>  
>  /* { dg-command { foo ([1,2] as int[]) } } */
>  /* { dg-output "2" } */
> diff --git a/testsuite/poke.pkl/promo-array-return-5.pk 
> b/testsuite/poke.pkl/promo-array-return-5.pk
> index 354fad4f..021497a7 100644
> --- a/testsuite/poke.pkl/promo-array-return-5.pk
> +++ b/testsuite/poke.pkl/promo-array-return-5.pk
> @@ -1,8 +1,8 @@
>  /* { dg-do run } */
>  
>  var x = 3;
> -fun foo = int[x-1]: { return [1,2]; }
> -fun bar = int[x-1][x-1]: { return [[1,2],[3,4]]; }
> +fun foo = int[x - 1]: { return [1,2]; }
> +fun bar = int[x - 1][x - 1]: { return [[1,2],[3,4]]; }
>  
>  /* { dg-command {foo[1]} } */
>  /* { dg-output "2" } */
> diff --git a/testsuite/poke.pkl/sub-integers-overflow-1.pk 
> b/testsuite/poke.pkl/sub-integers-overflow-1.pk
> index 3929cf0f..88be7988 100644
> --- a/testsuite/poke.pkl/sub-integers-overflow-1.pk
> +++ b/testsuite/poke.pkl/sub-integers-overflow-1.pk
> @@ -1,6 +1,6 @@
>  /* { dg-do run } */
>  
> -var x = 0x8000_0000 as int<32>;
> +var x = 0x8000_0000U as int<32>;
>  
>  /* { dg-command {  try x - 1; catch if E_overflow { print "caught\n"; } } } 
> */
>  /* { dg-output "caught" } */
> -- 
> 2.37.1
> 
> 
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]