Skip to content

Commit 0bfd28f

Browse files
committed
tinystdio: Use unsigned during signed int conversion to avoid overflow
The minimum value (e.g. LONG_MIN) cannot be converted without undefined behavior if we use signed values and perform the computation with positive values. Switch to unsigned, only converting upon return. Signed-off-by: Keith Packard <[email protected]>
1 parent cf54489 commit 0bfd28f

File tree

1 file changed

+9
-5
lines changed

1 file changed

+9
-5
lines changed

newlib/libc/tinystdio/strtoi.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@
5151
#define strtoi_isspace(c) isspace(c)
5252
#endif
5353

54+
#ifndef strtoi_signed
55+
#define strtoi_utype strtoi_type
56+
#endif
57+
5458
#if __HAVE_BUILTIN_MUL_OVERFLOW && __HAVE_BUILTIN_ADD_OVERFLOW && !defined(strtoi_signed)
5559
#define USE_OVERFLOW
5660
#endif
@@ -72,7 +76,7 @@ strtoi(const strtoi_char *__restrict nptr, strtoi_char **__restrict endptr, int
7276
#define FLAG_OFLOW 0x2 /* Value overflow */
7377

7478
const strtoi_uchar *s = (const strtoi_uchar *) nptr;
75-
strtoi_type val = 0;
79+
strtoi_utype val = 0;
7680
unsigned char flags = 0;
7781
strtoi_uint i;
7882

@@ -110,7 +114,7 @@ strtoi(const strtoi_char *__restrict nptr, strtoi_char **__restrict endptr, int
110114
#ifdef strtoi_signed
111115
/* works because strtoi_min = (strtoi_type) ((strtoi_utype) strtoi_max + 1) */
112116
strtoi_utype ucutoff = (strtoi_utype) strtoi_max + flags;
113-
strtoi_type cutoff = ucutoff / base;
117+
strtoi_utype cutoff = ucutoff / base;
114118
unsigned int cutlim = ucutoff % base;
115119
#else
116120
strtoi_type cutoff = strtoi_max / base;
@@ -141,7 +145,7 @@ strtoi(const strtoi_char *__restrict nptr, strtoi_char **__restrict endptr, int
141145
if (val > cutoff || (val == cutoff && i > cutlim))
142146
flags |= FLAG_OFLOW;
143147
else
144-
val = val * (strtoi_type) base + (strtoi_type) i;
148+
val = val * (strtoi_utype) base + (strtoi_utype) i;
145149
#endif
146150
/* Parsed another digit */
147151
nptr = (const strtoi_char *) s;
@@ -157,12 +161,12 @@ strtoi(const strtoi_char *__restrict nptr, strtoi_char **__restrict endptr, int
157161

158162
if (flags & FLAG_OFLOW) {
159163
#ifdef strtoi_signed
160-
val = (strtoi_type) ucutoff;
164+
val = ucutoff;
161165
#else
162166
val = strtoi_max;
163167
#endif
164168
errno = ERANGE;
165169
}
166170

167-
return val;
171+
return (strtoi_type) val;
168172
}

0 commit comments

Comments
 (0)