From 14bd48f3609aa3d8b3fd5c63608bd9383b47d49d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?= <grubba@grubba.org> Date: Wed, 29 Jun 2016 12:46:02 +0200 Subject: [PATCH] Roxen: Improved argument checking in make_http_headers(). Ensure that the formatted headers are valid. Fixes the entire class of bugs that [bug 7737] represents. --- src/modules/_Roxen/roxen.c | 34 ++++++++++++++++++++++++++++++--- src/modules/_Roxen/testsuite.in | 8 ++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/modules/_Roxen/roxen.c b/src/modules/_Roxen/roxen.c index 7b9ad8980f..ad29d27dae 100644 --- a/src/modules/_Roxen/roxen.c +++ b/src/modules/_Roxen/roxen.c @@ -305,6 +305,34 @@ static void f_hp_create( INT32 args ) /*! @endclass */ +static int valid_header_name(struct pike_string *s) +{ + ptrdiff_t i; + if (s->size_shift) return 0; + for (i = 0; i < s->len; i++) { + int c = s->str[i]; + if ((c == '\n') || (c == '\r') || (c == '\t') || (c == ' ') || (c == ':')) { + // The header formatting should not be broken by strange header names. + return 0; + } + } + return 1; +} + +static int valid_header_value(struct pike_string *s) +{ + ptrdiff_t i; + if (s->size_shift) return 0; + for (i = 0; i < s->len; i++) { + int c = s->str[i]; + if ((c == '\n') || (c == '\r')) { + // The header formatting should not be broken by strange header values. + return 0; + } + } + return 1; +} + static void f_make_http_headers( INT32 args ) /*! @decl string @ *! make_http_headers(mapping(string:string|array(string)) headers, @ @@ -332,10 +360,10 @@ static void f_make_http_headers( INT32 args ) /* loop to check len */ NEW_MAPPING_LOOP( m->data ) { - if( TYPEOF(k->ind) != PIKE_T_STRING || k->ind.u.string->size_shift ) + if( TYPEOF(k->ind) != PIKE_T_STRING || !valid_header_name(k->ind.u.string) ) Pike_error("Wrong argument type to make_http_headers(" "mapping(string(8bit):string(8bit)|array(string(8bit))) heads)\n"); - if( TYPEOF(k->val) == PIKE_T_STRING && !k->val.u.string->size_shift ) + if( TYPEOF(k->val) == PIKE_T_STRING && valid_header_value(k->val.u.string) ) total_len += k->val.u.string->len + 2 + k->ind.u.string->len + 2; else if( TYPEOF(k->val) == PIKE_T_ARRAY ) { @@ -343,7 +371,7 @@ static void f_make_http_headers( INT32 args ) ptrdiff_t i, kl = k->ind.u.string->len + 2 ; for( i = 0; i<a->size; i++ ) if( TYPEOF(a->item[i]) != PIKE_T_STRING || - a->item[i].u.string->size_shift ) + !valid_header_value(a->item[i].u.string) ) Pike_error("Wrong argument type to make_http_headers(" "mapping(string(8bit):string(8bit)|" "array(string(8bit))) heads)\n"); diff --git a/src/modules/_Roxen/testsuite.in b/src/modules/_Roxen/testsuite.in index bd3de371f3..be20188634 100644 --- a/src/modules/_Roxen/testsuite.in +++ b/src/modules/_Roxen/testsuite.in @@ -52,6 +52,14 @@ test_mkhttp( (["a":"1","b":"2"]), ({"a: 1","b: 2"}) ) test_mkhttp( (["a":"1","b":({"2","3"})]), ({"a: 1","b: 2","b: 3"}) ) test_mkhttp( (["a":"1","b":({"2","2"})]), ({"a: 1","b: 2","b: 2"}) ) +test_eval_error(_Roxen.make_http_headers((["a:1": "1"]))) +test_eval_error(_Roxen.make_http_headers((["a\rb": "1"]))) +test_eval_error(_Roxen.make_http_headers((["a\nb": "1"]))) +test_eval_error(_Roxen.make_http_headers(([" a:1": "1"]))) +test_eval_error(_Roxen.make_http_headers((["a": "1\r"]))) +test_eval_error(_Roxen.make_http_headers((["a": "1\n"]))) +test_eval_error(_Roxen.make_http_headers((["a": ({ "1\r\nb:2", "2\r\nc:2" }))))) + define(test_hp,[[ test_do( add_constant("hp", _Roxen.HeaderParser()) ) test_equal( hp->feed( $1 ), $2) -- GitLab