[Spice-devel] [vdagent-win PATCH] file-xfer: handle_start: use snprintf instead of sprintf_s

Frediano Ziglio fziglio at redhat.com
Sun Mar 3 16:22:23 UTC 2019


> On 2/28/19 3:12 PM, Frediano Ziglio wrote:
> >> On 2/25/19 4:12 PM, Frediano Ziglio wrote:
> >>>>
> >>>> When building with older mingw, sprintf_s does not
> >>>> always work as expected, but snprintf does.
> >>>>
> >>>> Also it's more consistent in the file.
> >>>>
> >>>> Note that when building with VS, snprintf becomes sprintf_s
> >>>>
> >>>
> >>> I think this could be a bug, from documentation:
> >>>
> >>> "If the buffer is too small for the formatted text, including the
> >>> terminating null, then the buffer is set to an empty string by placing a
> >>> null character at buffer[0], and the invalid parameter handler is
> >>> invoked"
> >>>
> >>> which is different from snprintf behaviour, _snprintf is probably what do
> >>> we want.
> >>
> >> Actually, I think we do want snprintf's behavior, not _snprintf.
> >> _snprintf does not guarantee null termination of the string.
> >>
> > 
> > Yes, you are right, sorry for the confusion.
> > 
> >> We should probably check the return value.
> > 
> > Well, yes, and in call to snprintf, even on Linux. Or continue to
> > ignore as we do.
> > 
> >> Also we can add a check that there is enough space and fail early.
> >>
> > 
> > This does not make sense, better to check later, it's easier.
> > But usually you just call snprintf and ignore if truncated,
> > I don't see why in this case we should make an exception.
> 
> 
> There is a check already with +3.

That check is protecting file_path, not dest_filename.

> We can make it with +1+6, so we know there is enough space:
> 

It's not enough, but the overflow on file_path is already
checked checking the return value of MultiByteToWideChar

> diff --git a/vdagent/file_xfer.cpp b/vdagent/file_xfer.cpp
> index c456bbe..7249b21 100644
> --- a/vdagent/file_xfer.cpp
> +++ b/vdagent/file_xfer.cpp
> @@ -93,8 +93,9 @@ void
> FileXfer::handle_start(VDAgentFileXferStartMessage* start,
> 
>       wlen = _tcslen(file_path);
>       // make sure we have enough space
> -    // (1 char for separator, 1 char for filename and 1 char for NUL
> terminator)
> -    if (wlen + 3 >= MAX_PATH) {
> +    // 1 = char for directory separator: "\"
> +    const size_t POSTFIX_LEN = 6; // up to 2 digits in parentheses and
> final NUL: " (xx)"
> +    if (wlen + 1 + POSTFIX_LEN >= MAX_PATH) {
>           vd_printf("error: file too long %ls\\%s", file_path, file_name);
>           return;
>       }
> 
> Uri.
> 

Looking at the code

        char dest_filename[SPICE_N_ELEMENTS(file_name) + POSTFIX_LEN];
        if (attempt == 0) {
            strcpy(dest_filename, file_name);
        } else {
            sprintf_s(dest_filename, SPICE_N_ELEMENTS(dest_filename),
                      "%.*s (%d)%s", int(extension - file_name), file_name, attempt, extension);
        }

so the dest_filename is large enough, you could even replace sprintf_s with a sprintf.

Frediano


More information about the Spice-devel mailing list