diff options
author | Daniel Stenberg <daniel@haxx.se> | 2021-07-07 14:51:17 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2021-07-08 10:05:39 +0200 |
commit | 9053dbbf62c7c9f4723959b557078a787ba6afec (patch) | |
tree | a6f859428ac17f47bd89e2dd72b5b11220525699 | |
parent | e7416cfd2bd58d256b8524f31ef22a43aa23a970 (diff) | |
download | curl-9053dbbf62c7c9f4723959b557078a787ba6afec.tar.gz |
msnprintf: return number of printed characters excluding null byte
... even when the output is "capped" by the maximum length argument.
Clarified in the docs.
Closes #7361
-rw-r--r-- | docs/libcurl/curl_mprintf.3 | 6 | ||||
-rw-r--r-- | lib/mprintf.c | 4 | ||||
-rw-r--r-- | lib/sendf.c | 6 | ||||
-rw-r--r-- | tests/libtest/lib557.c | 39 | ||||
-rw-r--r-- | tests/unit/unit1398.c | 12 | ||||
-rw-r--r-- | tests/unit/unit1652.c | 2 |
6 files changed, 51 insertions, 18 deletions
diff --git a/docs/libcurl/curl_mprintf.3 b/docs/libcurl/curl_mprintf.3 index 99f5236b8..e0a7af79d 100644 --- a/docs/libcurl/curl_mprintf.3 +++ b/docs/libcurl/curl_mprintf.3 @@ -246,8 +246,8 @@ not use them in new programs or projects. The \fBcurl_maprintf\fP and \fBcurl_mvaprintf\fP functions return a pointer to a newly allocated string, or NULL if it failed. -All other functions return the number of characters they actually -outputted. Note that this differs from how the POSIX versions of these -functions work. +All other functions return the number of characters actually printed +(excluding the null byte used to end output to strings). Note that this +sometimes differ from how the POSIX versions of these functions work. .SH "SEE ALSO" .BR printf "(3), " sprintf "(3), " fprintf "(3), " vprintf "(3) " diff --git a/lib/mprintf.c b/lib/mprintf.c index 529202686..7a1aec570 100644 --- a/lib/mprintf.c +++ b/lib/mprintf.c @@ -1017,9 +1017,11 @@ int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format, retcode = dprintf_formatf(&info, addbyter, format, ap_save); if((retcode != -1) && info.max) { /* we terminate this with a zero byte */ - if(info.max == info.length) + if(info.max == info.length) { /* we're at maximum, scrap the last letter */ info.buffer[-1] = 0; + retcode--; /* don't count the nul byte */ + } else info.buffer[0] = 0; } diff --git a/lib/sendf.c b/lib/sendf.c index d56399b77..14ca84bfe 100644 --- a/lib/sendf.c +++ b/lib/sendf.c @@ -246,8 +246,7 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...) size_t len; char buffer[MAXINFO + 2]; va_start(ap, fmt); - (void)mvsnprintf(buffer, MAXINFO, fmt, ap); - len = strlen(buffer); + len = mvsnprintf(buffer, MAXINFO, fmt, ap); va_end(ap); buffer[len++] = '\n'; buffer[len] = '\0'; @@ -267,8 +266,7 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...) size_t len; char error[CURL_ERROR_SIZE + 2]; va_start(ap, fmt); - (void)mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap); - len = strlen(error); + len = mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap); if(data->set.errorbuffer && !data->state.errorbuf) { strcpy(data->set.errorbuffer, error); diff --git a/tests/libtest/lib557.c b/tests/libtest/lib557.c index 00fbca38c..b6b8bec1f 100644 --- a/tests/libtest/lib557.c +++ b/tests/libtest/lib557.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -1541,8 +1541,9 @@ static int test_weird_arguments(void) buf[0] = 0; rc = curl_msnprintf(buf, sizeof(buf), "%d, %.*1$d", 500, 1); - if(rc != 256) { - printf("curl_mprintf() returned %d and not 256!\n", rc); + if(rc != sizeof(buf) - 1) { + printf("curl_mprintf() returned %d and not %d!\n", rc, + sizeof(buf) - 1); errors++; } @@ -1669,6 +1670,36 @@ static int test_float_formatting(void) } /* !checksrc! enable LONGLINE */ +static int test_return_codes(void) +{ + char buf[128]; + int rc; + + rc = curl_msnprintf(buf, 100, "%d", 9999); + if(rc != 4) + return 1; + + rc = curl_msnprintf(buf, 100, "%d", 99999); + if(rc != 5) + return 1; + + /* returns the length excluding the nul byte */ + rc = curl_msnprintf(buf, 5, "%d", 99999); + if(rc != 4) + return 1; + + /* returns the length excluding the nul byte */ + rc = curl_msnprintf(buf, 5, "%s", "helloooooooo"); + if(rc != 4) + return 1; + + /* returns the length excluding the nul byte */ + rc = curl_msnprintf(buf, 6, "%s", "helloooooooo"); + if(rc != 5) + return 1; + + return 0; +} int test(char *URL) { int errors = 0; @@ -1702,6 +1733,8 @@ int test(char *URL) errors += test_float_formatting(); + errors += test_return_codes(); + if(errors) return TEST_ERR_MAJOR_BAD; else diff --git a/tests/unit/unit1398.c b/tests/unit/unit1398.c index 43e1f47a5..e73ce24b0 100644 --- a/tests/unit/unit1398.c +++ b/tests/unit/unit1398.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -64,27 +64,27 @@ fail_unless(!strcmp(output, "012"), "wrong output"); /* negative width */ rc = curl_msnprintf(output, 8, "%-8s", str); -fail_unless(rc == 8, "return code should be 8"); +fail_unless(rc == 7, "return code should be 7"); fail_unless(!strcmp(output, "bug "), "wrong output"); /* larger width that string length */ rc = curl_msnprintf(output, 8, "%8s", str); -fail_unless(rc == 8, "return code should be 8"); +fail_unless(rc == 7, "return code should be 7"); fail_unless(!strcmp(output, " bu"), "wrong output"); /* output a number in a limited output */ rc = curl_msnprintf(output, 4, "%d", 10240); -fail_unless(rc == 4, "return code should be 4"); +fail_unless(rc == 3, "return code should be 3"); fail_unless(!strcmp(output, "102"), "wrong output"); /* padded strings */ rc = curl_msnprintf(output, 16, "%8s%8s", str, str); -fail_unless(rc == 16, "return code should be 16"); +fail_unless(rc == 15, "return code should be 15"); fail_unless(!strcmp(output, " bug bu"), "wrong output"); /* padded numbers */ rc = curl_msnprintf(output, 16, "%8d%8d", 1234, 5678); -fail_unless(rc == 16, "return code should be 16"); +fail_unless(rc == 15, "return code should be 15"); fail_unless(!strcmp(output, " 1234 567"), "wrong output"); UNITTEST_STOP diff --git a/tests/unit/unit1652.c b/tests/unit/unit1652.c index 26f11e483..56dad0c34 100644 --- a/tests/unit/unit1652.c +++ b/tests/unit/unit1652.c @@ -108,7 +108,7 @@ fail_unless(verify(result, "(nil)") == 0, "Passing NULL as string"); /* A string just long enough to not be truncated */ memset(input, '\0', sizeof(input)); -memset(input, 'A', 2048); +memset(input, 'A', 2047); Curl_infof(data, "%s", input); fail_unless(strlen(result) == 2048, "No truncation of infof input"); fail_unless(verify(result, input) == 0, "No truncation of infof input"); |