Fix potential overflow due to Str.c

This commit is contained in:
Tatsuya Kinoshita
2021-02-26 19:38:51 +09:00
parent f0aff94b2b
commit f29533cc7b

42
Str.c
View File

@@ -50,8 +50,8 @@ Str
Strnew_size(int n) Strnew_size(int n)
{ {
Str x = GC_MALLOC(sizeof(struct _Str)); Str x = GC_MALLOC(sizeof(struct _Str));
if (n < 0) if (n < 0 || n >= STR_SIZE_MAX)
n = 0; n = STR_SIZE_MAX - 1;
x->ptr = GC_MALLOC_ATOMIC(n + 1); x->ptr = GC_MALLOC_ATOMIC(n + 1);
x->ptr[0] = '\0'; x->ptr[0] = '\0';
x->area_size = n + 1; x->area_size = n + 1;
@@ -69,10 +69,13 @@ Strnew_charp(const char *p)
return Strnew(); return Strnew();
x = GC_MALLOC(sizeof(struct _Str)); x = GC_MALLOC(sizeof(struct _Str));
n = strlen(p) + 1; n = strlen(p) + 1;
if (n < 0 || n > STR_SIZE_MAX)
n = STR_SIZE_MAX;
x->ptr = GC_MALLOC_ATOMIC(n); x->ptr = GC_MALLOC_ATOMIC(n);
x->area_size = n; x->area_size = n;
x->length = n - 1; x->length = n - 1;
bcopy((void *)p, (void *)x->ptr, n); bcopy((void *)p, (void *)x->ptr, n - 1);
x->ptr[x->length] = '\0';
return x; return x;
} }
@@ -98,6 +101,8 @@ Strnew_charp_n(const char *p, int n)
if (p == NULL) if (p == NULL)
return Strnew_size(n); return Strnew_size(n);
x = GC_MALLOC(sizeof(struct _Str)); x = GC_MALLOC(sizeof(struct _Str));
if (n < 0 || n >= STR_SIZE_MAX)
n = STR_SIZE_MAX - 1;
x->ptr = GC_MALLOC_ATOMIC(n + 1); x->ptr = GC_MALLOC_ATOMIC(n + 1);
x->area_size = n + 1; x->area_size = n + 1;
x->length = n; x->length = n;
@@ -151,15 +156,19 @@ Strcopy_charp(Str x, const char *y)
STR_LENGTH_CHECK(x); STR_LENGTH_CHECK(x);
if (y == NULL) { if (y == NULL) {
x->length = 0; x->length = 0;
x->ptr[0] = '\0';
return; return;
} }
len = strlen(y); len = strlen(y);
if (len < 0 || len >= STR_SIZE_MAX)
len = STR_SIZE_MAX - 1;
if (x->area_size < len + 1) { if (x->area_size < len + 1) {
GC_free(x->ptr); GC_free(x->ptr);
x->ptr = GC_MALLOC_ATOMIC(len + 1); x->ptr = GC_MALLOC_ATOMIC(len + 1);
x->area_size = len + 1; x->area_size = len + 1;
} }
bcopy((void *)y, (void *)x->ptr, len + 1); bcopy((void *)y, (void *)x->ptr, len);
x->ptr[len] = '\0';
x->length = len; x->length = len;
} }
@@ -171,16 +180,19 @@ Strcopy_charp_n(Str x, const char *y, int n)
STR_LENGTH_CHECK(x); STR_LENGTH_CHECK(x);
if (y == NULL) { if (y == NULL) {
x->length = 0; x->length = 0;
x->ptr[0] = '\0';
return; return;
} }
if (len < 0 || len >= STR_SIZE_MAX)
len = STR_SIZE_MAX - 1;
if (x->area_size < len + 1) { if (x->area_size < len + 1) {
GC_free(x->ptr); GC_free(x->ptr);
x->ptr = GC_MALLOC_ATOMIC(len + 1); x->ptr = GC_MALLOC_ATOMIC(len + 1);
x->area_size = len + 1; x->area_size = len + 1;
} }
bcopy((void *)y, (void *)x->ptr, n); bcopy((void *)y, (void *)x->ptr, len);
x->ptr[n] = '\0'; x->ptr[len] = '\0';
x->length = n; x->length = len;
} }
void void
@@ -191,10 +203,18 @@ Strcat_charp_n(Str x, const char *y, int n)
STR_LENGTH_CHECK(x); STR_LENGTH_CHECK(x);
if (y == NULL) if (y == NULL)
return; return;
if (n < 0)
n = STR_SIZE_MAX - 1;
newlen = x->length + n + 1; newlen = x->length + n + 1;
if (newlen < 0 || newlen > STR_SIZE_MAX) {
newlen = STR_SIZE_MAX;
n = newlen - x->length - 1;
}
if (x->area_size < newlen) { if (x->area_size < newlen) {
char *old = x->ptr; char *old = x->ptr;
newlen = newlen * 3 / 2; newlen = newlen * 3 / 2;
if (newlen < 0 || newlen > STR_SIZE_MAX)
newlen = STR_SIZE_MAX;
x->ptr = GC_MALLOC_ATOMIC(newlen); x->ptr = GC_MALLOC_ATOMIC(newlen);
x->area_size = newlen; x->area_size = newlen;
bcopy((void *)old, (void *)x->ptr, x->length); bcopy((void *)old, (void *)x->ptr, x->length);
@@ -320,6 +340,10 @@ Strdelete(Str s, int pos, int n)
{ {
int i; int i;
STR_LENGTH_CHECK(s); STR_LENGTH_CHECK(s);
if (pos < 0 || s->length < pos)
return;
if (n < 0)
n = STR_SIZE_MAX - pos - 1;
if (s->length <= pos + n) { if (s->length <= pos + n) {
s->ptr[pos] = '\0'; s->ptr[pos] = '\0';
s->length = pos; s->length = pos;
@@ -335,6 +359,8 @@ void
Strtruncate(Str s, int pos) Strtruncate(Str s, int pos)
{ {
STR_LENGTH_CHECK(s); STR_LENGTH_CHECK(s);
if (pos < 0 || s->length < pos)
return;
s->ptr[pos] = '\0'; s->ptr[pos] = '\0';
s->length = pos; s->length = pos;
} }
@@ -347,7 +373,7 @@ Strshrink(Str s, int n)
s->length = 0; s->length = 0;
s->ptr[0] = '\0'; s->ptr[0] = '\0';
} }
else { else if (n > 0) {
s->length -= n; s->length -= n;
s->ptr[s->length] = '\0'; s->ptr[s->length] = '\0';
} }