summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2021-07-07 14:51:17 +0200
committerDaniel Stenberg <daniel@haxx.se>2021-07-08 10:05:39 +0200
commit9053dbbf62c7c9f4723959b557078a787ba6afec (patch)
treea6f859428ac17f47bd89e2dd72b5b11220525699
parente7416cfd2bd58d256b8524f31ef22a43aa23a970 (diff)
downloadcurl-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.36
-rw-r--r--lib/mprintf.c4
-rw-r--r--lib/sendf.c6
-rw-r--r--tests/libtest/lib557.c39
-rw-r--r--tests/unit/unit1398.c12
-rw-r--r--tests/unit/unit1652.c2
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");