change resize functions to handle overflow gravefully, added backport header for C89 types and macros, moved some functions to extensions.c/.h

AuthorKonata <konata@posteo.jp>
Date
Commit3144ea2ef24360e7d77e6caf120c74ca0cd9b9fb
Parenta12f15d
12 files changed, 218 insertions(+), 75 deletions(-)
Ainclude/cutils/backport.h
@@ -0,0 +1,119 @@
1+#ifndef BACKPORT_H
2+#define BACKPORT_H
3+
4+#include <limits.h>
5+#if __STDC_VERSION__ >= 199901L
6+ #include <stdint.h>
7+ #include <stdbool.h>
8+#else
9+
10+ #ifndef SIZE_MAX
11+ #define SIZE_MAX (size_t)-1
12+ #endif /* SIZE_MAX */
13+
14+ #ifndef CUTILS_NO_BOOL
15+ typedef enum {false = 0, true = !false} bool;
16+ #endif /* CUTILS_NO_BOOL */
17+
18+ #ifndef CUTILS_NO_MAX
19+ #ifdef ULLONG_MAX
20+ #define UINTMAX_MAX ULLONG_MAX
21+ typedef unsigned long long uintmax_t;
22+ #else
23+ #define UINTMAX_MAX ULONG_MAX
24+ typedef unsigned long uintmax_t;
25+ #endif
26+ #ifdef LLONG_MAX
27+ #define INTMAX_MAX LLONG_MAX
28+ #define INTMAX_MIN LLONG_MIN
29+ typedef unsigned long long intmax_t;
30+ #else
31+ #define INTMAX_MAX LONG_MAX
32+ #define INTMAX_MIN LONG_MIN
33+ typedef unsigned long intmax_t;
34+ #endif
35+ #endif /* CUTILS_NO_MAX */
36+
37+ #ifndef CUTILS_NO_LEAST
38+ #define UINTLEAST8_MAX UCHAR_MAX
39+ typedef unsigned char uint_least8_t;
40+ #define UINT8_C(x) ((uint_least8_t)x)
41+
42+ #define UINTLEAST16_MAX USHRT_MAX
43+ typedef unsigned short uint_least16_t;
44+ #define UINT16_C(x) ((uint_least16_t)x)
45+
46+ #define UINTLEAST32_MAX ULONG_MAX
47+ typedef unsigned long uint_least32_t;
48+ #define UINT32_C(x) ((uint_least32_t)x)
49+
50+ #ifdef ULLONG_MAX
51+ #define UINTLEAST64_MAX ULLONG_MAX
52+ typedef unsigned long long uint_least64_t;
53+ #define UINT64_C(x) ((uint_least64_t)x)
54+ #endif /* ULLONG_MAX */
55+
56+
57+ #define INTLEAST8_MAX SCHAR_MAX
58+ #define INTLEAST8_MIN SCHAR_MIN
59+ typedef signed char int_least8_t;
60+ #define INT8_C(x) ((int_least8_t)x)
61+
62+ #define INTLEAST16_MAX SHRT_MAX
63+ #define INTLEAST16_MIN SHRT_MIN
64+ typedef short int_least16_t;
65+ #define INT16_C(x) ((int_least16_t)x)
66+
67+ #define INTLEAST32_MAX LONG_MAX
68+ #define INTLEAST32_MIN LONG_MIN
69+ typedef long int_least32_t;
70+ #define INT32_C(x) ((int_least32_t)x)
71+
72+ #ifdef LLONG_MAX
73+ #define INTLEAST64_MAX LLONG_MAX
74+ #define INTLEAST64_MIN LLONG_MIN
75+ typedef long long int_least64_t;
76+ #define INT64_C(x) ((int_least64_t)x)
77+ #endif /* LLONG_MAX */
78+ #endif /* CUTILS_NO_LEAST */
79+
80+ /* for now just copy least types */
81+ #ifndef CUTILS_NO_FAST
82+ #define UINTFAST8_MAX UCHAR_MAX
83+ typedef unsigned char uint_fast8_t;
84+
85+ #define UINTFAST16_MAX USHRT_MAX
86+ typedef unsigned short uint_fast16_t;
87+
88+ #define UINTFAST32_MAX ULONG_MAX
89+ typedef unsigned long uint_fast32_t;
90+
91+ #ifdef ULLONG_MAX
92+ #define UINTFAST64_MAX ULLONG_MAX
93+ typedef unsigned long long uint_fast64_t;
94+ #endif /* ULLONG_MAX */
95+
96+
97+ #define INTFAST8_MAX SCHAR_MAX
98+ #define INTFAST8_MIN SCHAR_MIN
99+ typedef signed char int_fast8_t;
100+
101+ #define INTFAST16_MAX SHRT_MAX
102+ #define INTFAST16_MIN SHRT_MIN
103+ typedef short int_fast16_t;
104+
105+ #define INTFAST32_MAX LONG_MAX
106+ #define INTFAST32_MIN LONG_MIN
107+ typedef long int_fast32_t;
108+
109+ #ifdef LLONG_MAX
110+ #define INTFAST64_MAX LLONG_MAX
111+ #define INTFAST64_MIN LLONG_MIN
112+ typedef long long int_fast64_t;
113+ #endif /* LLONG_MAX */
114+ #endif /* CUTILS_NO_FAST */
115+
116+#endif
117+
118+
119+#endif /* BACKPORT_H */
Minclude/cutils/common.h
@@ -1,19 +1,8 @@
11 #ifndef CUTILS_COMMON_H
22 #define CUTILS_COMMON_H
33
4-#include <stddef.h>
4+#include <cutils/backport.h>
55 #include <cutils/hedley.h>
6-#ifndef SIZE_MAX
7- #define SIZE_MAX (size_t)-1;
8-#endif
9-
10-#if __STDC_VERSION__ >= 199901L
11- #include <stdbool.h>
12-#else
13- #ifndef CUTILS_NO_BOOL
14- typedef enum {false = 0, true = 1} bool;
15- #endif
16-#endif
17-
6+#include <cutils/extensions.h>
187
198 #endif /* CUTILS_COMMON_H */
Minclude/cutils/cutils.h
@@ -6,5 +6,7 @@
66 #include <cutils/misc.h>
77 #include <cutils/byte_array.h>
88 #include <cutils/linked-list.h>
9+#include <cutils/extensions.h>
10+#include <cutils/backport.h>
911
1012 #endif /* CUTILS_H */
Ainclude/cutils/extensions.h
@@ -0,0 +1,42 @@
1+#ifndef EXTENSIONS_H
2+#define EXTENSIONS_H
3+
4+#include <cutils/hedley.h>
5+#include <errno.h>
6+#include <stdlib.h>
7+#include <cutils/backport.h>
8+#include <string.h>
9+#include <ctype.h>
10+
11+int strcmp_nocase(const char* s1, const char* s2);
12+int strncmp_nocase(const char* s1, const char* s2, size_t n);
13+
14+HEDLEY_INLINE
15+static void* reallocsafe(void *ptr, size_t nmemb, size_t size)
16+{
17+ size_t new_size = nmemb * size;
18+
19+ if(nmemb != 0 && new_size / nmemb != size)
20+ {
21+ errno = ENOMEM;
22+ return NULL;
23+ } else {
24+ return realloc(ptr, new_size);
25+ }
26+}
27+
28+HEDLEY_INLINE
29+static void* reallocsafe_inc(void *ptr, size_t nmemb, size_t size, size_t add)
30+{
31+ if(SIZE_MAX - add < size)
32+ {
33+ errno = ENOMEM;
34+ return NULL;
35+ } else {
36+ return reallocsafe(ptr, nmemb, size+add);
37+ }
38+}
39+
40+
41+
42+#endif /* EXTENSIONS_H */
Minclude/cutils/misc.h
@@ -20,8 +20,6 @@
2020 #include <ctype.h>
2121
2222 #if __STDC_VERSION__ >= 199901L
23- #include <stdint.h>
24- typedef uintmax_t max_uint_t;
2523 #ifdef UINT32_MAX
2624 uint32_t ntoh32(uint32_t const net);
2725 #endif
@@ -34,8 +32,6 @@
3432 memcpy(item2, tmp, length);
3533 free(tmp);
3634 }
37-#else
38- typedef unsigned long max_uint_t;
3935 #endif
4036
4137 HEDLEY_INLINE
@@ -68,13 +64,11 @@ static void memqswap(void* item1, void* item2, void* tmp, size_t length)
6864 #endif
6965
7066 void sleep_ms(unsigned int milliseconds);
71-int strcmp_nocase(const char* s1, const char* s2);
72-int strncmp_nocase(const char* s1, const char* s2, size_t n);
7367
7468 #if __STDC_VERSION__ >= 201112L
7569 struct timespec timespec_diff(const struct timespec* old_ts, const struct timespec* new_ts);
7670 struct timespec timespec_add(const struct timespec* ts_1, const struct timespec* ts_2);
77- max_uint_t timespec_ms(const struct timespec* ts);
71+ uintmax_t timespec_ms(const struct timespec* ts);
7872 #endif
7973
8074 #endif /* MISC_H */
Mmeson.build
@@ -1,7 +1,7 @@
11 project('cutils', 'c')
22
33 WARNINGS = ['-Wall', '-Wpedantic', '-Wextra', '-Wnull-dereference', '-Wshadow', '-Wconversion', '-Wstrict-prototypes', '-Wmissing-prototypes', '-Wcast-qual', '-Wstrict-overflow=5', '-Wunreachable-code', '-Wno-unused-parameter', '-Wno-unused-function']
4-CFLAGS = ['-std=c89', '-fstrict-aliasing', '-fPIC'] + WARNINGS
4+CFLAGS = ['-std=c89', '-fstrict-aliasing', '-fPIC', '-Wno-long-long'] + WARNINGS
55
66 subdir('include')
77 subdir('src')
Msrc/byte_array.c
@@ -68,7 +68,7 @@ bool bytearray_insert(Bytearray* bytearray, size_t index, const void* item)
6868 size_t length = bytearray->length;
6969 size_t size = bytearray->element_size;
7070
71- if(index > length || !bytearray_adjust_size(bytearray, length+1))
71+ if(index > length || length == SIZE_MAX || !bytearray_adjust_size(bytearray, length+1))
7272 return false;
7373
7474 memmove(bytearray->items+index*size+1*size, bytearray->items+index*size, (length*size-index*size)*sizeof(*bytearray->items));
@@ -86,7 +86,7 @@ void bytearray_remove(Bytearray* bytearray, size_t index, void (*rmv)(void*))
8686 if(rmv)
8787 rmv(&bytearray->items[index*elsize]);
8888
89- memmove(bytearray->items+index*elsize, bytearray->items+index*elsize+1*elsize, (length*elsize-index*elsize-1*elsize)*sizeof(*bytearray->items));
89+ memmove(bytearray->items+index*elsize, bytearray->items+index*elsize+1*elsize, length*elsize-index*elsize-1*elsize);
9090 bytearray->length--;
9191 }
9292 }
@@ -95,10 +95,8 @@ bool bytearray_adjust_size(Bytearray* bytearray, size_t size)
9595 {
9696 while(bytearray->capacity < size)
9797 {
98- size_t capacity = bytearray->capacity;
99- size_t elsize = bytearray->element_size;
10098 char* tmp = bytearray->items;
101- bytearray->items = realloc(bytearray->items, capacity*elsize*2*sizeof(*bytearray->items));
99+ bytearray->items = reallocsafe_inc(bytearray->items, sizeof(*bytearray->items), bytearray->capacity, bytearray->capacity);
102100 if(!bytearray->items)
103101 {
104102 bytearray->items = tmp;
@@ -113,10 +111,8 @@ bool bytearray_shrink(Bytearray* bytearray)
113111 {
114112 while(bytearray->capacity > bytearray->length*2)
115113 {
116- size_t capacity = bytearray->capacity;
117- size_t size = bytearray->element_size;
118114 char* tmp = bytearray->items;
119- bytearray->items = realloc(bytearray->items, (capacity*size)/(2*sizeof(*bytearray->items)));
115+ bytearray->items = realloc(bytearray->items, (bytearray->capacity*bytearray->element_size)/2);
120116 if(!bytearray->items)
121117 {
122118 bytearray->items = tmp;
Msrc/dyn_string.c
@@ -37,7 +37,7 @@ void string_remove_range(String* string, size_t index, size_t length)
3737
3838 bool string_insert(String* string, size_t index, char character)
3939 {
40- if(index > string->length || !string_adjust_size(string, string->length))
40+ if(index > string->length || string->length == SIZE_MAX || !string_adjust_size(string, string->length))
4141 return false;
4242
4343 memmove(string->chars+index+1, string->chars+index, (string->length-index)*sizeof(*string->chars));
@@ -117,7 +117,7 @@ bool string_adjust_size(String* string, size_t size)
117117 while(string->capacity < size)
118118 {
119119 char* tmp = string->chars;
120- string->chars = realloc(string->chars, string->capacity*2*(sizeof(*string->chars)));
120+ string->chars = reallocsafe_inc(string->chars, sizeof(*string->chars), string->capacity, string->capacity);
121121 if(!string->chars)
122122 {
123123 string->chars = tmp;
Asrc/extensions.c
@@ -0,0 +1,40 @@
1+#include <cutils/extensions.h>
2+
3+int strcmp_nocase(const char* s1, const char* s2)
4+{
5+ const unsigned char* p1 = (const unsigned char*)s1;
6+ const unsigned char* p2 = (const unsigned char*)s2;
7+ unsigned char c1, c2;
8+
9+ do
10+ {
11+ c1 = (unsigned char)tolower(*p1++);
12+ c2 = (unsigned char)tolower(*p2++);
13+ if (c1 == '\0')
14+ return c1 - c2;
15+ }
16+ while (c1 == c2);
17+
18+ return c1 - c2;
19+}
20+
21+int strncmp_nocase(const char* s1, const char* s2, size_t n)
22+{
23+ const unsigned char* p1 = (const unsigned char*)s1;
24+ const unsigned char* p2 = (const unsigned char*)s2;
25+ unsigned char c1, c2;
26+
27+ if(n == 0)
28+ return 0;
29+
30+ do
31+ {
32+ c1 = (unsigned char)tolower(*p1++);
33+ c2 = (unsigned char)tolower(*p2++);
34+ if (c1 == '\0')
35+ return c1 - c2;
36+ }
37+ while (c1 == c2 && --n);
38+
39+ return c1 - c2;
40+}
Msrc/meson.build
@@ -1,4 +1,4 @@
1-src = ['vector.c', 'dyn_string.c', 'misc.c', 'byte_array.c', 'linked-list.c']
1+src = ['vector.c', 'dyn_string.c', 'misc.c', 'byte_array.c', 'linked-list.c', 'extensions.c']
22 srctest = src + ['test.c']
33
44 cutils_lib = library('cutils', src, include_directories : inc, install: true)
Msrc/misc.c
@@ -10,45 +10,6 @@ void sleep_ms(unsigned int milliseconds)
1010 #endif
1111 }
1212
13-int strcmp_nocase(const char* s1, const char* s2)
14-{
15- const unsigned char* p1 = (const unsigned char*)s1;
16- const unsigned char* p2 = (const unsigned char*)s2;
17- unsigned char c1, c2;
18-
19- do
20- {
21- c1 = (unsigned char)tolower(*p1++);
22- c2 = (unsigned char)tolower(*p2++);
23- if (c1 == '\0')
24- return c1 - c2;
25- }
26- while (c1 == c2);
27-
28- return c1 - c2;
29-}
30-
31-int strncmp_nocase(const char* s1, const char* s2, size_t n)
32-{
33- const unsigned char* p1 = (const unsigned char*)s1;
34- const unsigned char* p2 = (const unsigned char*)s2;
35- unsigned char c1, c2;
36-
37- if(n == 0)
38- return 0;
39-
40- do
41- {
42- c1 = (unsigned char)tolower(*p1++);
43- c2 = (unsigned char)tolower(*p2++);
44- if (c1 == '\0')
45- return c1 - c2;
46- }
47- while (c1 == c2 && --n);
48-
49- return c1 - c2;
50-}
51-
5213 #if __STDC_VERSION__ >= 199901L
5314 #ifdef UINT32_MAX
5415 uint32_t ntoh32(uint32_t const net)
@@ -98,8 +59,8 @@ struct timespec timespec_add(const struct timespec* ts_1, const struct timespec*
9859 }
9960
10061
101-max_uint_t timespec_ms(const struct timespec* ts)
62+uintmax_t timespec_ms(const struct timespec* ts)
10263 {
103- return (max_uint_t)ts->tv_sec * 1000 + (max_uint_t)ts->tv_nsec/1000000;
64+ return (uintmax_t)ts->tv_sec * 1000 + (uintmax_t)ts->tv_nsec/1000000;
10465 }
10566 #endif
Msrc/vector.c
@@ -76,7 +76,7 @@ size_t* vector_find(const Vector* haystack, const void* needle, int (*cmp)(const
7676
7777 bool vector_insert(Vector* vector, size_t index, void* item)
7878 {
79- if(index > vector->length || !vector_adjust_size(vector, vector->length+1))
79+ if(index > vector->length || vector->length == SIZE_MAX || !vector_adjust_size(vector, vector->length+1))
8080 return false;
8181
8282 memmove(vector->items+index+1, vector->items+index, (vector->length-index)*sizeof(*vector->items));
@@ -90,7 +90,7 @@ bool vector_adjust_size(Vector* vector, size_t size)
9090 while(vector->capacity < size)
9191 {
9292 void** tmp = vector->items;
93- vector->items = realloc(vector->items, vector->capacity*2*sizeof(*vector->items));
93+ vector->items = reallocsafe_inc(vector->items, sizeof(*vector->items), vector->capacity, vector->capacity);
9494 if(!vector->items)
9595 {
9696 vector->items = tmp;