diff --git a/src/modules/_Roxen/roxen.c b/src/modules/_Roxen/roxen.c index 7b9ad8980fe53d9f2a6845f7278703ae26ba774d..ad29d27dae37014f158f104fb94eeb78ff7b786d 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 bd3de371f3a627b9a443566360d5e81974b526c2..be20188634752db6e4370a14b04c5d933dd40721 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)