[hackers] [scc] Add correct parsing of integer constants || Roberto E. Vargas Caballero

From: <git_AT_suckless.org>
Date: Mon, 7 Sep 2015 16:55:29 +0200 (CEST)

commit 609bb6b7743e8a37538a2701df3aaa3b652ebfb7
Author: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
AuthorDate: Mon Sep 7 16:31:39 2015 +0200
Commit: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
CommitDate: Mon Sep 7 16:31:39 2015 +0200

    Add correct parsing of integer constants
    
    Until this moment there was no check of overflow, and there was no
    cast to bigger types when the constant was bigger than the type declared by
    the user.

diff --git a/cc1/fold.c b/cc1/fold.c
index a9e474e..d464173 100644
--- a/cc1/fold.c
+++ b/cc1/fold.c
_AT_@ -507,6 +507,7 @@ simplify(int op, Type *tp, Node *lp, Node *rp)
 Node *
 castcode(Node *np, Type *newtp)
 {
+ TUINT mask;
         Type *oldtp = np->type;
         Symbol aux, *sym, *osym = np->sym;
 
_AT_@ -517,6 +518,7 @@ castcode(Node *np, Type *newtp)
         case PTR:
         case INT:
         case ENUM:
+ mask = ones(newtp->size);
                 switch (oldtp->op) {
                 case PTR:
                 case INT:
_AT_@ -524,21 +526,25 @@ castcode(Node *np, Type *newtp)
                         if (newtp->sign == oldtp->sign)
                                 aux.u = osym->u;
                         if (newtp->sign && !oldtp->sign)
- aux.u.i = osym->u.u;
+ aux.u.i = osym->u.u & mask;
                         else if (!newtp->sign && oldtp->sign)
- aux.u.u = osym->u.u;
+ aux.u.u = osym->u.u & mask;
                         break;
                 case FLOAT:
- if (newtp->sign)
+ if (newtp->sign) {
                                 aux.u.i = osym->u.f;
- else
+ aux.u.i &= mask;
+ } else {
                                 aux.u.u = osym->u.f;
+ aux.u.u &= mask;
+ }
                         break;
                 default:
                         goto noconstant;
                 }
                 break;
         case FLOAT:
+ /* FIXME: The cast can be from another floar type */
                 aux.u.f = (oldtp->sign) ? osym->u.i : osym->u.u;
                 break;
         default:
diff --git a/cc1/lex.c b/cc1/lex.c
index 3df6ab1..0a4132a 100644
--- a/cc1/lex.c
+++ b/cc1/lex.c
_AT_@ -201,6 +201,55 @@ tok2str(void)
         input->begin = input->p;
 }
 
+static Symbol *
+readint(char *s, int base, Symbol *sym)
+{
+ Type *tp = sym->type;
+ struct limits *lim = getlimits(tp);
+ TUINT u, val, max, factor = 1;
+ int c;
+
+ max = (tp->sign) ? lim->max.u : lim->max.i;
+ switch (*s++) {
+ case '-': factor = -1; break;
+ default: --s;
+ case '+': factor = 1; break;
+ }
+
+ for (u = 0; isxdigit(c = *s++); u = u * base + val) {
+ val = (c <= '9') ? c - '0' : 10 + c - 'A';
+ if (u <= max/base + val)
+ continue;
+ if (tp->sign) {
+ if (tp == inttype)
+ tp = longtype;
+ else if (tp == longtype)
+ tp == llongtype;
+ else {
+ errorp("overflow in integer constant");
+ break;
+ }
+ } else {
+ if (tp == uinttype)
+ tp = ulongtype;
+ else if (tp == ulongtype)
+ tp == ullongtype;
+ else {
+ errorp("overflow in integer constant");
+ break;
+ }
+ }
+ sym->type = tp;
+ }
+
+ if (tp->sign)
+ sym->u.i = u * factor;
+ else
+ sym->u.u = u;
+
+ return sym;
+}
+
 static unsigned
 integer(char *s, char base)
 {
_AT_@ -233,10 +282,7 @@ convert:
         sym = newsym(NS_IDEN);
         sym->type = tp;
         sym->flags |= ISCONSTANT;
- v = strtol(s, NULL, base);
- if (tp == inttype)
- sym->u.i = v;
- yylval.sym = sym;
+ yylval.sym = readint(s, base, sym);
         return CONSTANT;
 }
 
diff --git a/cc1/types.c b/cc1/types.c
index 2c86d23..5f13f6f 100644
--- a/cc1/types.c
+++ b/cc1/types.c
_AT_@ -17,24 +17,6 @@
  */
 static struct limits limits[][4] = {
         {
- { /* 0 = signed 1 byte */
- .min.i = -127,
- .max.i = 127
- },
- { /* 1 = signed 2 byte */
- .min.i = -32767,
- .max.i = 327677
- },
- { /* 2 = signed 4 byte */
- .min.i = -2147483647L,
- .max.i = 2147483647L
- },
- { /* 3 = signed 8 byte */
- .min.i = -9223372036854775807LL,
- .max.i = 9223372036854775807LL,
- }
- },
- {
                 { /* 0 = unsigned 1 byte */
                         .min.u = 0,
                         .max.u = 255
_AT_@ -53,6 +35,24 @@ static struct limits limits[][4] = {
                 }
         },
         {
+ { /* 0 = signed 1 byte */
+ .min.i = -127,
+ .max.i = 127
+ },
+ { /* 1 = signed 2 byte */
+ .min.i = -32767,
+ .max.i = 32767
+ },
+ { /* 2 = signed 4 byte */
+ .min.i = -2147483647L,
+ .max.i = 2147483647L
+ },
+ { /* 3 = signed 8 byte */
+ .min.i = -9223372036854775807LL,
+ .max.i = 9223372036854775807LL,
+ }
+ },
+ {
                 {
                         /* 0 = float 4 bytes */
                         .min.f = -1,
Received on Mon Sep 07 2015 - 16:55:29 CEST

This archive was generated by hypermail 2.3.0 : Mon Sep 07 2015 - 17:00:14 CEST