[pve-devel] [PATCH] fix read after string end

Thomas Lamprecht t.lamprecht at proxmox.com
Tue Jun 18 15:19:09 CEST 2019


On 6/18/19 2:59 PM, Dominik Csapak wrote:
> On 6/18/19 2:37 PM, Thomas Lamprecht wrote:
>> On 6/18/19 2:24 PM, Dominik Csapak wrote:
>>> outs is not a zero-terminated string but has its length given by
>>> outslen, so use that (with a maximum of the size of msg)
>>>
>>> Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
>>> ---
>>>   RADOS.xs | 8 +++++++-
>>>   1 file changed, 7 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/RADOS.xs b/RADOS.xs
>>> index f3f5516..7eca024 100644
>>> --- a/RADOS.xs
>>> +++ b/RADOS.xs
>>> @@ -131,8 +131,14 @@ CODE:
>>>         if (ret < 0) {
>>>           char msg[4096];
>>> -        snprintf(msg, sizeof(msg), "mon_command failed - %s\n", outs);
>>> +        if (outslen > sizeof(msg)) {
>>> +            outslen = sizeof(msg);
>>> +        }
>>
>> we always have some static string part which already consumes from
>> msg available space, so above is wrong? Why not just omit it, snprintf
>> will never print more than sizeof(msg) anyway?
> 
> outslen is size_t but we need an int for the field precision width
> so we have to cast but do not want to get some negative value in case
> it is too big, i just used the msg size as an upper limit
> we never write more than sizeof(msg)

a bit of a strange cast..

glibc just omits the precission if it's negative:
https://sourceware.org/git/?p=glibc.git;a=blob;f=stdio-common/vfprintf-internal.c;h=ead2b04cb96b0346dde876e5d41418fae2cc8b0d;hb=HEAD#l1554

Also from the man page (from parts you left out in your quote below
as irrelevant ;)
> A negative precision is taken as if the  precision  were omitted.

So that's also documented behavior, so I'd just pass it along, as
above looks like a bug (missed static length from "mon_command fa.."
and is a bit confusing, to me at least.

> 
> better would be to subtract the size of "mon_command failed - \n"
> but i did not want to copy that string, and some kind of define
> or const char * seemed a little much for this (the error
> messages are not that big in most cases anyway)
> 
>>
>>> +        snprintf(msg, sizeof(msg), "mon_command failed - %.*s\n", (int)outslen, outs);
>>
>> so, .* is using the field width functionallity of the *printf methods,
>> man snprintfs tells me:
>>
>>> Field width
>>> ... In no case does a nonexistent or small field width cause truncation of a field; if the result of  a  conversion  is
>>> wider than the field width, the field is expanded to contain the conversion result.
>>
>> So is this actually working?
> 
> this is not the field width, but the field precision
> man snprintf:
> 
> Precision
>  An  optional  precision, in the form of a period ('.')  followed by an
>  optional decimal digit string. [...] This gives the [...]
>  maximum  number of characters to be printed from a
>  string for s and S conversions.
> 
> (irrelevant parts omitted)
> 
> so it is the maximum number of characters for the string

OK, thanks for clarifying, maybe note something like that somewhere
in the vicinity of such a commit the next time :)

> 
>>
>>>           rados_buffer_free(outs);
>>> +        if (outbuf != NULL) {
>>> +            rados_buffer_free(outbuf);
>>> +        }
>>>           die(msg);
>>>       }
>>>  
>>





More information about the pve-devel mailing list