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
This commit is contained in:
Daniel Stenberg 2021-07-07 14:51:17 +02:00
Родитель e7416cfd2b
Коммит 9053dbbf62
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 5CC908FDB71E12C2
6 изменённых файлов: 51 добавлений и 18 удалений

Просмотреть файл

@ -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) "

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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);

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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");