Skip to content

Commit

Permalink
grn_text_vprintf windows: fix a bug auto buffer expansion doesn't work
Browse files Browse the repository at this point in the history
vsnprintf() with not enough buffer returns -1 not the number of
written characters. It's not different with the document:

https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/vsnprintf-vsnprintf-vsnprintf-l-vsnwprintf-vsnwprintf-l?view=vs-2019

> If the buffer size specified by count is not sufficiently large to
> contain the output specified by format and argptr, the return value
> of vsnprintf is the number of characters that would be written, not
> counting the null character
  • Loading branch information
kou committed May 8, 2019
1 parent 3169ddb commit f05bcb1
Showing 1 changed file with 24 additions and 29 deletions.
53 changes: 24 additions & 29 deletions lib/str.c
Expand Up @@ -2599,49 +2599,44 @@ grn_text_vprintf(grn_ctx *ctx, grn_obj *bulk, const char *format, va_list args)
format, copied_args);
va_end(copied_args);

if (0 <= written_size && written_size < rest_size) {
if (written_size < rest_size) {
is_written = GRN_TRUE;
}
}

if (!is_written) {
#ifdef WIN32
# define N_NEW_SIZES 3
int i;
int new_sizes[N_NEW_SIZES];
grn_rc rc;
int required_size;

new_sizes[0] = GRN_BULK_REST(bulk) + strlen(format) * 2;
new_sizes[1] = new_sizes[0] + 4096;
new_sizes[2] = new_sizes[0] + 65536;
va_copy(copied_args, args);
required_size = vsnprintf(NULL, 0, format, copied_args);
va_end(copied_args);

for (i = 0; i < N_NEW_SIZES; i++) {
if (required_size < 0) {
return GRN_INVALID_ARGUMENT;
}
required_size++; /* for terminate '\0'. */
rc = grn_bulk_reserve(ctx, bulk, required_size);
if (rc) {
return rc;
}
va_copy(copied_args, args);
written_size = vsnprintf(GRN_BULK_CURR(bulk), required_size,
format, copied_args);
va_end(copied_args);
#else /* WIN32 */
if (written_size >= 0) {
grn_rc rc;
int new_size = new_sizes[i];
va_list copied_args;
int required_size = written_size + 1; /* "+ 1" for terminate '\0'. */

rc = grn_bulk_reserve(ctx, bulk, GRN_BULK_VSIZE(bulk) + new_size);
rc = grn_bulk_reserve(ctx, bulk, required_size);
if (rc) {
return rc;
}
va_copy(copied_args, args);
written_size = vsnprintf(GRN_BULK_CURR(bulk), new_size,
format, copied_args);
va_end(copied_args);
if (written_size != -1) {
break;
}
written_size = vsnprintf(GRN_BULK_CURR(bulk), required_size,
format, args);
}
# undef N_NEW_SIZES
#else /* WIN32 */
grn_rc rc;
int required_size = written_size + 1; /* "+ 1" for terminate '\0'. */

rc = grn_bulk_reserve(ctx, bulk, GRN_BULK_VSIZE(bulk) + required_size);
if (rc) {
return rc;
}
written_size = vsnprintf(GRN_BULK_CURR(bulk), required_size,
format, args);
#endif /* WIN32 */
}

Expand Down

0 comments on commit f05bcb1

Please sign in to comment.