[PATCH] perl module: fix SSI parameter termination bug

Matthew Daley mattjd at gmail.com
Tue Mar 13 08:43:25 UTC 2012


On Tue, Mar 13, 2012 at 9:28 PM, Maxim Dounin <mdounin at mdounin.ru> wrote:
> Hello!
>
> On Tue, Mar 13, 2012 at 08:34:33PM +1300, Matthew Daley wrote:
>
>> Hi,
>>
>> There is a small issue in the handling of the SSI command provided by
>> the Perl module.
>>
>> It NULL-terminates the 'sub' parameter value before passing it to
>> ngx_http_perl_eval_anon_sub, but this has the problem that if the
>> parameter's length is the maximum allowable for SSI commands, it will
>> write the NULL byte just past the end of the allocated buffer:
>>
>> ==14669== Invalid write of size 1
>> ==14669==    at 0x80A79E3: ngx_http_perl_ssi (ngx_http_perl_module.c:384)
>> ==14669==    by 0x80904CF: ngx_http_ssi_body_filter (ngx_http_ssi_filter_module.c:794)
>
> [...]
>
>> I have attached a patch which attempts to fix the problem by creating
>> an appropriately-sized buffer and NULL-terminating a copy of the
>> string to eval.
>
> Nice catch, thanks.  The patch is wrong though, see below.
>
> [...]
>
>> @@ -381,7 +382,6 @@
>>      ctx->ssi = ssi_ctx;
>>
>>      handler = params[NGX_HTTP_PERL_SSI_SUB];
>> -    handler->data[handler->len] = '\0';
>>
>>      {
>>
>> @@ -392,7 +392,7 @@
>>
>>      /* the code is disabled to force the precompiled perl code using only */
>>
>> -    ngx_http_perl_eval_anon_sub(aTHX_ handler, &sv);
>> +    ngx_http_perl_eval_anon_sub(aTHX_ r->pool, handler, &sv);
>
> This code is indeed disabled, as stated in the comment above, it's
> under #if 0.

Yeah, just wanted to make sure that it'd still work if re-enabled.

>
> The null-terminated string in handler is required for
>
>    sv = newSVpvn((char *) handler->data, handler->len);
>
> below though, and your patch will break it.

Hmm, I was going by this info in the perlapi documentation, which made
me think that newSVpvn didn't need it:
"Notice that you can choose to specify the length of the string to be
assigned by using sv_setpvn , newSVpvn , or newSVpv , or you may allow
Perl to calculate the length by using sv_setpv or by specifying 0 as
the second argument to newSVpv . Be warned, though, that Perl will
determine the string's length by using strlen , which depends on the
string terminating with a NUL character."

However I see below that it says:
"All SVs that contain strings should be terminated with a NUL
character. If it is not NUL-terminated there is a risk of core dumps
and corruptions from code which passes the string to C functions or
system calls which expect a NUL-terminated string. Perl's own
functions typically add a trailing NUL for this reason."

So you are right.

>
> Correct solution would be to reserve space for NUL character in
> ssi module instead.  Quick and dirty patch which should work:
>
> --- a/src/http/modules/ngx_http_ssi_filter_module.c
> +++ b/src/http/modules/ngx_http_ssi_filter_module.c
> @@ -1204,7 +1204,7 @@ ngx_http_ssi_parse(ngx_http_request_t *r
>
>                 if (ctx->value_buf == NULL) {
>                     ctx->param->value.data = ngx_pnalloc(r->pool,
> -                                                         ctx->value_len);
> +                                                         ctx->value_len + 1);
>                     if (ctx->param->value.data == NULL) {
>                         return NGX_ERROR;
>                     }
>

I wasn't sure if changing the SSI allocation code was appropriate in
this case, but since newSVpvn really does need the NULL termination,
this is indeed a better idea.



More information about the nginx-devel mailing list