diff --git a/blob.c b/blob.c index abcc9f2..93321ed 100644 --- a/blob.c +++ b/blob.c @@ -16,13 +16,23 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include + #include "blob.h" static bool blob_buffer_grow(struct blob_buf *buf, int minlen) { - struct blob_buf *new; - int delta = ((minlen / 256) + 1) * 256; + void *new; + int delta; + + if (minlen < 0 || minlen > INT_MAX - 256) + return false; + + delta = ((minlen / 256) + 1) * 256; + if (buf->buflen < 0 || delta > INT_MAX - buf->buflen) + return false; + new = realloc(buf->buf, buf->buflen + delta); if (new) { buf->buf = new; @@ -58,7 +68,9 @@ blob_buf_grow(struct blob_buf *buf, int required) { int offset_head = attr_to_offset(buf, buf->head); - if ((buf->buflen + required) > BLOB_ATTR_LEN_MASK) + if (required < 0 || buf->buflen < 0) + return false; + if (required > BLOB_ATTR_LEN_MASK - buf->buflen) return false; if (!buf->grow || !buf->grow(buf, required)) return false; @@ -326,7 +338,7 @@ struct blob_attr * blob_memdup(const struct blob_attr *attr) { struct blob_attr *ret; - int size = blob_pad_len(attr); + size_t size = blob_pad_len(attr); ret = malloc(size); if (!ret) diff --git a/blobmsg.c b/blobmsg.c index d87d607..fdf3337 100644 --- a/blobmsg.c +++ b/blobmsg.c @@ -13,6 +13,8 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include + #include "blobmsg.h" static const int blob_type[__BLOBMSG_TYPE_LAST] = { @@ -163,18 +165,30 @@ int blobmsg_parse_array(const struct blobmsg_policy *policy, int policy_len, return 0; } +/* + * Upper bound on the number of policy entries blobmsg_parse() will + * accept. The pslen scratch array is allocated on the stack via + * alloca(); 4096 entries cap the per-call stack use at + * 4096 * sizeof(uint16_t) = 8 KiB, which comfortably fits the typical + * 8 KiB thread default while being far above any realistic policy + * size used in practice (a few dozen entries). + */ +#define BLOBMSG_PARSE_MAX_POLICY 4096 + int blobmsg_parse(const struct blobmsg_policy *policy, int policy_len, struct blob_attr **tb, void *data, unsigned int len) { const struct blobmsg_hdr *hdr; struct blob_attr *attr; - uint8_t *pslen; + uint16_t *pslen; int i; memset(tb, 0, policy_len * sizeof(*tb)); if (!data || !len) return -EINVAL; - pslen = alloca(policy_len); + if (policy_len < 0 || policy_len > BLOBMSG_PARSE_MAX_POLICY) + return -ENOMEM; + pslen = alloca(policy_len * sizeof(*pslen)); for (i = 0; i < policy_len; i++) { if (!policy[i].name) continue; @@ -240,7 +254,7 @@ blobmsg_new(struct blob_buf *buf, int type, const char *name, int payload_len, v if (!attr) return NULL; - attr->id_len |= be32_to_cpu(BLOB_ATTR_EXTENDED); + attr->id_len |= cpu_to_be32(BLOB_ATTR_EXTENDED); hdr = blob_data(attr); hdr->namelen = cpu_to_be16(namelen); @@ -328,6 +342,8 @@ blobmsg_alloc_string_buffer(struct blob_buf *buf, const char *name, unsigned int struct blob_attr *attr; void *data_dest; + if (maxlen == (unsigned int)-1) + return NULL; maxlen++; attr = blobmsg_new(buf, BLOBMSG_TYPE_STRING, name, maxlen, &data_dest); if (!attr) @@ -344,11 +360,19 @@ blobmsg_realloc_string_buffer(struct blob_buf *buf, unsigned int maxlen) { struct blob_attr *attr = blob_next(buf->head); int offset = attr_to_offset(buf, blob_next(buf->head)) + blob_pad_len(attr) - BLOB_COOKIE; - int required = maxlen + 1 - (buf->buflen - offset); + int required; - if (required <= 0) + if (maxlen >= INT_MAX) + return NULL; + + if (buf->buflen < 0 || offset < 0 || offset > buf->buflen) + return NULL; + + if ((int)maxlen + 1 <= buf->buflen - offset) goto out; + required = (int)maxlen + 1 - (buf->buflen - offset); + if (!blob_buf_grow(buf, required)) return NULL; attr = blob_next(buf->head); diff --git a/blobmsg_json.c b/blobmsg_json.c index 31eec09..04bb9a1 100644 --- a/blobmsg_json.c +++ b/blobmsg_json.c @@ -112,8 +112,8 @@ bool blobmsg_add_json_from_string(struct blob_buf *b, const char *str) struct strbuf { - int len; - int pos; + size_t len; + size_t pos; char *buf; blobmsg_json_format_t custom_format; @@ -122,16 +122,28 @@ struct strbuf { int indent_level; }; -static bool blobmsg_puts(struct strbuf *s, const char *c, int len) +/* + * Minimum and growth slack for the JSON strbuf. The minimum size + * keeps malloc(0) out of setup_strbuf() and is large enough to hold + * any short scalar serialisation ("null", "true", "false", small + * numbers) without an immediate realloc. The same value is added on + * each grow in blobmsg_puts() so that successive small writes are + * amortised across a few extra bytes per realloc. + */ +#define STRBUF_MIN_SIZE 16 + +static bool blobmsg_puts(struct strbuf *s, const char *c, size_t len) { size_t new_len; char *new_buf; - if (len <= 0) + if (!len) return true; - if (s->pos + len >= s->len) { - new_len = s->len + 16 + len; + if (s->len - s->pos <= len) { + if (len > SIZE_MAX - STRBUF_MIN_SIZE - s->len) + return false; + new_len = s->len + STRBUF_MIN_SIZE + len; new_buf = realloc(s->buf, new_len); if (!new_buf) return false; @@ -170,7 +182,7 @@ static void blobmsg_format_string(struct strbuf *s, const char *str) blobmsg_puts(s, "\"", 1); for (p = (unsigned char *) str, last = p; *p; p++) { char escape = '\0'; - int len; + size_t len; switch(*p) { case '\b': @@ -260,7 +272,7 @@ static void blobmsg_format_element(struct strbuf *s, struct blob_attr *attr, boo snprintf(buf, sizeof(buf), "%" PRId64, (int64_t) be64_to_cpu(*(uint64_t *)data)); break; case BLOBMSG_TYPE_DOUBLE: - snprintf(buf, sizeof(buf), "%lf", blobmsg_get_double(attr)); + snprintf(buf, sizeof(buf), "%.17g", blobmsg_get_double(attr)); break; case BLOBMSG_TYPE_STRING: blobmsg_format_string(s, data); @@ -303,6 +315,8 @@ static void blobmsg_format_json_list(struct strbuf *s, struct blob_attr *attr, i static void setup_strbuf(struct strbuf *s, struct blob_attr *attr, blobmsg_json_format_t cb, void *priv, int indent) { s->len = blob_len(attr); + if (s->len < STRBUF_MIN_SIZE) + s->len = STRBUF_MIN_SIZE; s->buf = malloc(s->len); s->pos = 0; s->custom_format = cb; @@ -333,7 +347,7 @@ char *blobmsg_format_json_with_cb(struct blob_attr *attr, bool list, blobmsg_jso else blobmsg_format_element(&s, attr, false, false); - if (!s.len) { + if (!s.pos) { free(s.buf); return NULL; } @@ -360,7 +374,7 @@ char *blobmsg_format_json_value_with_cb(struct blob_attr *attr, blobmsg_json_for blobmsg_format_element(&s, attr, true, false); - if (!s.len) { + if (!s.pos) { free(s.buf); return NULL; } diff --git a/jshn.c b/jshn.c index 9887bfe..4b947e1 100644 --- a/jshn.c +++ b/jshn.c @@ -338,6 +338,7 @@ static int jshn_parse_file(const char *path) struct stat sb; int ret = 0; char *fbuf; + ssize_t n; int fd; if ((fd = open(path, O_RDONLY)) == -1) { @@ -351,13 +352,20 @@ static int jshn_parse_file(const char *path) return 3; } - if (!(fbuf = calloc(1, sb.st_size+1))) { + if (sb.st_size < 0 || (uintmax_t)sb.st_size >= SIZE_MAX) { + fprintf(stderr, "File %s has invalid size\n", path); + close(fd); + return 3; + } + + if (!(fbuf = calloc(1, (size_t)sb.st_size + 1))) { fprintf(stderr, "Error allocating memory for %s\n", path); close(fd); return 3; } - if (read(fd, fbuf, sb.st_size) != sb.st_size) { + n = read(fd, fbuf, (size_t)sb.st_size); + if (n < 0 || n != sb.st_size) { fprintf(stderr, "Error reading %s\n", path); free(fbuf); close(fd); diff --git a/json_script.c b/json_script.c index 7177e9c..de7e546 100644 --- a/json_script.c +++ b/json_script.c @@ -426,17 +426,24 @@ static int json_process_expr(struct json_call *call, struct blob_attr *cur) static int eval_string(struct json_call *call, struct blob_buf *buf, const char *name, const char *pattern) { - char *dest, *next, *str; + char *dest, *next, *str, *buffer; + size_t pattern_len; int len = 0; bool var = false; char c = '%'; - dest = blobmsg_alloc_string_buffer(buf, name, 0); - if (!dest) + pattern_len = strlen(pattern); + buffer = malloc(pattern_len + 1); + if (!buffer) return -1; + memcpy(buffer, pattern, pattern_len + 1); + next = buffer; - next = alloca(strlen(pattern) + 1); - strcpy(next, pattern); + dest = blobmsg_alloc_string_buffer(buf, name, 0); + if (!dest) { + free(buffer); + return -1; + } for (str = next; str; str = next) { const char *cur; @@ -487,6 +494,7 @@ static int eval_string(struct json_call *call, struct blob_buf *buf, const char dest[len] = 0; blobmsg_add_string_buffer(buf); + free(buffer); if (var) return -1; @@ -639,13 +647,11 @@ static void __json_script_file_free(struct json_script_file *f) { struct json_script_file *next; - if (!f) - return; - - next = f->next; - free(f); - - __json_script_file_free(next); + while (f) { + next = f->next; + free(f); + f = next; + } } void diff --git a/md5.c b/md5.c index 3f8ad28..6941013 100644 --- a/md5.c +++ b/md5.c @@ -321,9 +321,14 @@ int md5sum(const char *file, void *md5_buf) md5_begin(&ctx); do { - int len = fread(buf, 1, sizeof(buf), f); - if (!len) + size_t len = fread(buf, 1, sizeof(buf), f); + if (!len) { + if (ferror(f)) { + fclose(f); + return -1; + } break; + } md5_hash(buf, len, &ctx); ret += len; diff --git a/tests/cram/test_blobmsg.t b/tests/cram/test_blobmsg.t index 0c192c5..67a9d80 100644 --- a/tests/cram/test_blobmsg.t +++ b/tests/cram/test_blobmsg.t @@ -35,7 +35,7 @@ check that blobmsg is producing expected results: \tworld : 2 (str) (esc) } - [*] blobmsg to json: {"message":"Hello, world!","testdata":{"dbl-min":0.000000,"dbl-max":179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000,"foo":false,"poo":true,"moo-min":true,"moo-max":true,"bar-min":-32768,"bar-max":32767,"baz-min":-2147483648,"baz-max":2147483647,"taz-min":-9223372036854775808,"taz-max":9223372036854775807,"world":"2"},"list":[false,true,true,true,-32768,32767,-2147483648,2147483647,-9223372036854775808,9223372036854775807,0.000000,179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000]} + [*] blobmsg to json: {"message":"Hello, world!","testdata":{"dbl-min":2.2250738585072014e-308,"dbl-max":1.7976931348623157e+308,"foo":false,"poo":true,"moo-min":true,"moo-max":true,"bar-min":-32768,"bar-max":32767,"baz-min":-2147483648,"baz-max":2147483647,"taz-min":-9223372036854775808,"taz-max":9223372036854775807,"world":"2"},"list":[false,true,true,true,-32768,32767,-2147483648,2147483647,-9223372036854775808,9223372036854775807,2.2250738585072014e-308,1.7976931348623157e+308]} [*] blobmsg from json: Message: Hello, world! @@ -102,7 +102,7 @@ check that blobmsg is producing expected results: \tworld : 2 (str) (esc) } - [*] blobmsg to json: {"message":"Hello, world!","testdata":{"dbl-min":0.000000,"dbl-max":179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000,"foo":false,"poo":true,"moo-min":true,"moo-max":true,"bar-min":-32768,"bar-max":32767,"baz-min":-2147483648,"baz-max":2147483647,"taz-min":-9223372036854775808,"taz-max":9223372036854775807,"world":"2"},"list":[false,true,true,true,-32768,32767,-2147483648,2147483647,-9223372036854775808,9223372036854775807,0.000000,179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000]} + [*] blobmsg to json: {"message":"Hello, world!","testdata":{"dbl-min":2.2250738585072014e-308,"dbl-max":1.7976931348623157e+308,"foo":false,"poo":true,"moo-min":true,"moo-max":true,"bar-min":-32768,"bar-max":32767,"baz-min":-2147483648,"baz-max":2147483647,"taz-min":-9223372036854775808,"taz-max":9223372036854775807,"world":"2"},"list":[false,true,true,true,-32768,32767,-2147483648,2147483647,-9223372036854775808,9223372036854775807,2.2250738585072014e-308,1.7976931348623157e+308]} [*] blobmsg from json: Message: Hello, world! @@ -169,7 +169,7 @@ check that blobmsg is producing expected results: \tworld : 2 (str) (esc) } - [*] blobmsg to json: {"message":"Hello, world!","testdata":{"dbl-min":0.000000,"dbl-max":179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000,"foo":false,"poo":true,"moo-min":true,"moo-max":true,"bar-min":-32768,"bar-max":32767,"baz-min":-2147483648,"baz-max":2147483647,"taz-min":-9223372036854775808,"taz-max":9223372036854775807,"world":"2"},"list":[false,true,true,true,-32768,32767,-2147483648,2147483647,-9223372036854775808,9223372036854775807,0.000000,179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000]} + [*] blobmsg to json: {"message":"Hello, world!","testdata":{"dbl-min":2.2250738585072014e-308,"dbl-max":1.7976931348623157e+308,"foo":false,"poo":true,"moo-min":true,"moo-max":true,"bar-min":-32768,"bar-max":32767,"baz-min":-2147483648,"baz-max":2147483647,"taz-min":-9223372036854775808,"taz-max":9223372036854775807,"world":"2"},"list":[false,true,true,true,-32768,32767,-2147483648,2147483647,-9223372036854775808,9223372036854775807,2.2250738585072014e-308,1.7976931348623157e+308]} [*] blobmsg from json: Message: Hello, world! @@ -236,7 +236,7 @@ check that blobmsg is producing expected results: \tworld : 2 (str) (esc) } - [*] blobmsg to json: {"message":"Hello, world!","testdata":{"dbl-min":0.000000,"dbl-max":179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000,"foo":false,"poo":true,"moo-min":true,"moo-max":true,"bar-min":-32768,"bar-max":32767,"baz-min":-2147483648,"baz-max":2147483647,"taz-min":-9223372036854775808,"taz-max":9223372036854775807,"world":"2"},"list":[false,true,true,true,-32768,32767,-2147483648,2147483647,-9223372036854775808,9223372036854775807,0.000000,179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000]} + [*] blobmsg to json: {"message":"Hello, world!","testdata":{"dbl-min":2.2250738585072014e-308,"dbl-max":1.7976931348623157e+308,"foo":false,"poo":true,"moo-min":true,"moo-max":true,"bar-min":-32768,"bar-max":32767,"baz-min":-2147483648,"baz-max":2147483647,"taz-min":-9223372036854775808,"taz-max":9223372036854775807,"world":"2"},"list":[false,true,true,true,-32768,32767,-2147483648,2147483647,-9223372036854775808,9223372036854775807,2.2250738585072014e-308,1.7976931348623157e+308]} [*] blobmsg from json: Message: Hello, world! diff --git a/tests/cram/test_blobmsg_types.t b/tests/cram/test_blobmsg_types.t index 190e1f2..4def0e6 100644 --- a/tests/cram/test_blobmsg_types.t +++ b/tests/cram/test_blobmsg_types.t @@ -40,7 +40,7 @@ check that blobmsg is producing expected results: double_max: 1.797693e+308 double_min: 2.225074e-308 - [*] blobmsg to json: {"string":"Hello, world!","int64_max":9223372036854775807,"int64_min":-9223372036854775808,"int32_max":2147483647,"int32_min":-2147483648,"int16_max":32767,"int16_min":-32768,"int8_max":true,"int8_min":true,"double_max":179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000,"double_min":0.000000} + [*] blobmsg to json: {"string":"Hello, world!","int64_max":9223372036854775807,"int64_min":-9223372036854775808,"int32_max":2147483647,"int32_min":-2147483648,"int16_max":32767,"int16_min":-32768,"int8_max":true,"int8_min":true,"double_max":1.7976931348623157e+308,"double_min":2.2250738585072014e-308} [*] blobmsg from json: string: Hello, world! @@ -53,7 +53,7 @@ check that blobmsg is producing expected results: int8_max: 1 int8_min: 1 double_max: 1.797693e+308 - double_min: 0.000000e+00 + double_min: 2.225074e-308 [*] blobmsg from json/cast_u64: string: Hello, world! @@ -66,7 +66,7 @@ check that blobmsg is producing expected results: int8_max: 1 int8_min: 1 double_max: 1.797693e+308 - double_min: 0.000000e+00 + double_min: 2.225074e-308 [*] blobmsg from json/cast_s64: string: Hello, world! @@ -79,4 +79,4 @@ check that blobmsg is producing expected results: int8_max: 1 int8_min: 1 double_max: 1.797693e+308 - double_min: 0.000000e+00 + double_min: 2.225074e-308 diff --git a/udebug.c b/udebug.c index e39a32c..1b43f69 100644 --- a/udebug.c +++ b/udebug.c @@ -625,14 +625,14 @@ int udebug_entry_vprintf(struct udebug_buf *buf, const char *fmt, va_list ap) va_copy(ap2, ap); len = vsnprintf(str, UDEBUG_MIN_ALLOC_LEN, fmt, ap2); va_end(ap2); - if (len <= UDEBUG_MIN_ALLOC_LEN) + if (len < UDEBUG_MIN_ALLOC_LEN) goto out; if (ptr->len + len > buf->data_size / 2) return -1; udebug_buf_alloc(buf, ofs, len + 1); - len = vsnprintf(str, len, fmt, ap); + len = vsnprintf(str, len + 1, fmt, ap); out: ptr->len += len; diff --git a/uloop.c b/uloop.c index fa86675..403218b 100644 --- a/uloop.c +++ b/uloop.c @@ -85,12 +85,12 @@ int uloop_fd_add(struct uloop_fd *sock, unsigned int flags); static void set_signo(uint64_t *signums, int signo) { if (signo >= 1 && signo <= 64) - *signums |= (1u << (signo - 1)); + *signums |= (UINT64_C(1) << (signo - 1)); } static bool get_signo(uint64_t signums, int signo) { - return (signo >= 1) && (signo <= 64) && (signums & (1u << (signo - 1))); + return (signo >= 1) && (signo <= 64) && (signums & (UINT64_C(1) << (signo - 1))); } static void signal_consume(struct uloop_fd *fd, unsigned int events) @@ -121,8 +121,15 @@ static struct uloop_fd waker_fd = { static void waker_init_fd(int fd) { - fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); - fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); + int flags; + + flags = fcntl(fd, F_GETFD); + if (flags >= 0) + fcntl(fd, F_SETFD, flags | FD_CLOEXEC); + + flags = fcntl(fd, F_GETFL); + if (flags >= 0) + fcntl(fd, F_SETFL, flags | O_NONBLOCK); } static int waker_init(void) @@ -235,7 +242,7 @@ static void uloop_run_events(int64_t timeout) int uloop_fd_add(struct uloop_fd *sock, unsigned int flags) { - unsigned int fl; + int fl; int ret; if (!(flags & (ULOOP_READ | ULOOP_WRITE | ULOOP_PRIORITY))) @@ -243,8 +250,8 @@ int uloop_fd_add(struct uloop_fd *sock, unsigned int flags) if (!sock->registered && !(flags & ULOOP_BLOCKING)) { fl = fcntl(sock->fd, F_GETFL, 0); - fl |= O_NONBLOCK; - fcntl(sock->fd, F_SETFL, fl); + if (fl >= 0) + fcntl(sock->fd, F_SETFL, fl | O_NONBLOCK); } ret = register_poll(sock, flags); diff --git a/usock.c b/usock.c index 2ac84de..b2a2e99 100644 --- a/usock.c +++ b/usock.c @@ -27,19 +27,28 @@ #include #include #include +#include #include -#include +#include #include "usock.h" #include "utils.h" static void usock_set_flags(int sock, unsigned int type) { - if (!(type & USOCK_NOCLOEXEC)) - fcntl(sock, F_SETFD, fcntl(sock, F_GETFD) | FD_CLOEXEC); + int flags; + + if (!(type & USOCK_NOCLOEXEC)) { + flags = fcntl(sock, F_GETFD); + if (flags >= 0) + fcntl(sock, F_SETFD, flags | FD_CLOEXEC); + } - if (type & USOCK_NONBLOCK) - fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK); + if (type & USOCK_NONBLOCK) { + flags = fcntl(sock, F_GETFL); + if (flags >= 0) + fcntl(sock, F_SETFL, flags | O_NONBLOCK); + } } static int usock_connect(int type, struct sockaddr *sa, int sa_len, int family, int socktype, bool server) @@ -106,13 +115,14 @@ usock_inet_notimeout(int type, struct addrinfo *result, void *addr) static int poll_restart(struct pollfd *fds, int nfds, int timeout) { struct timespec ts, cur; + int64_t remaining; int msec = timeout % 1000; int ret; clock_gettime(CLOCK_MONOTONIC, &ts); ts.tv_nsec += msec * 1000000; - if (ts.tv_nsec > 1000000000) { + if (ts.tv_nsec >= 1000000000) { ts.tv_sec++; ts.tv_nsec -= 1000000000; } @@ -124,10 +134,11 @@ static int poll_restart(struct pollfd *fds, int nfds, int timeout) return ret; clock_gettime(CLOCK_MONOTONIC, &cur); - timeout = (ts.tv_sec - cur.tv_sec) * 1000; - timeout += (ts.tv_nsec - cur.tv_nsec) / 1000000; - if (timeout <= 0) + remaining = ((int64_t)ts.tv_sec - (int64_t)cur.tv_sec) * 1000; + remaining += (ts.tv_nsec - cur.tv_nsec) / 1000000; + if (remaining <= 0) return 0; + timeout = remaining > INT_MAX ? INT_MAX : (int)remaining; } } @@ -145,13 +156,16 @@ static int usock_check_connect(int fd) static int usock_timeout_remaining(struct timespec *deadline) { struct timespec cur; - int msec; + int64_t msec; clock_gettime(CLOCK_MONOTONIC, &cur); - msec = (deadline->tv_sec - cur.tv_sec) * 1000; + msec = ((int64_t)deadline->tv_sec - (int64_t)cur.tv_sec) * 1000; msec += (deadline->tv_nsec - cur.tv_nsec) / 1000000; - return msec > 0 ? msec : 0; + if (msec > INT_MAX) + return INT_MAX; + + return msec > 0 ? (int)msec : 0; } #define USOCK_MAX_CANDIDATES 8 @@ -202,6 +216,7 @@ int usock_inet_timeout(int type, const char *host, const char *service, int n_candidates, n_active = 0; int sock = -1; int fd, delay, i, j; + int flags; if (getaddrinfo(host, service, &hints, &result)) return -1; @@ -292,8 +307,11 @@ int usock_inet_timeout(int type, const char *host, const char *service, } if (sock >= 0) { - if (!(type & USOCK_NONBLOCK)) - fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) & ~O_NONBLOCK); + if (!(type & USOCK_NONBLOCK)) { + flags = fcntl(sock, F_GETFL); + if (flags >= 0) + fcntl(sock, F_SETFL, flags & ~O_NONBLOCK); + } if (addr) memcpy(addr, rp->ai_addr, rp->ai_addrlen); } diff --git a/ustream.c b/ustream.c index d200dba..ff3aa05 100644 --- a/ustream.c +++ b/ustream.c @@ -16,6 +16,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include #include @@ -498,6 +499,8 @@ int ustream_vprintf(struct ustream *s, const char *format, va_list arg) maxlen -= wr; return ustream_write_buffered(s, buf, maxlen, wr); } else { + if (maxlen == INT_MAX) + return 0; buf = malloc(maxlen + 1); if (!buf) return 0; @@ -527,6 +530,8 @@ int ustream_vprintf(struct ustream *s, const char *format, va_list arg) if (maxlen < buflen) return wr; + if (maxlen == INT_MAX) + return wr; buf = malloc(maxlen + 1); if (!buf) return wr; diff --git a/utils.c b/utils.c index 82af887..6d4c36c 100644 --- a/utils.c +++ b/utils.c @@ -38,14 +38,28 @@ void *__calloc_a(size_t len, ...) void *ret; void **cur_addr; size_t cur_len; - int alloc_len = 0; + size_t alloc_len = 0; char *ptr; va_start(ap, len); va_copy(ap1, ap); - foreach_arg(ap1, cur_addr, cur_len, &ret, len) - alloc_len += (cur_len + C_PTR_ALIGN - 1 ) & C_PTR_MASK; + foreach_arg(ap1, cur_addr, cur_len, &ret, len) { + size_t aligned; + + if (cur_len > SIZE_MAX - (C_PTR_ALIGN - 1)) { + va_end(ap1); + va_end(ap); + return NULL; + } + aligned = (cur_len + C_PTR_ALIGN - 1) & C_PTR_MASK; + if (aligned > SIZE_MAX - alloc_len) { + va_end(ap1); + va_end(ap); + return NULL; + } + alloc_len += aligned; + } va_end(ap1); ptr = calloc(1, alloc_len);