Move name/value validation functions to src
nghttp2 library itself now accept octet header/value pairs, completely not restricted by HTTP/1 header name/value rule. The applications may impose restriction about them using validators.
This commit is contained in:
parent
0e4b3d435e
commit
707a0b4103
|
@ -2143,8 +2143,6 @@ int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags,
|
||||||
* :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
|
* :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
|
||||||
* The |nva| includes empty name, or name which contains invalid
|
* The |nva| includes empty name, or name which contains invalid
|
||||||
* characters.
|
* characters.
|
||||||
* :enum:`NGHTTP2_ERR_STREAM_CLOSED`
|
|
||||||
* The stream is already closed or does not exist.
|
|
||||||
* :enum:`NGHTTP2_ERR_NOMEM`
|
* :enum:`NGHTTP2_ERR_NOMEM`
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -550,46 +550,6 @@ nghttp2_settings_entry* nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
|
||||||
return iv_copy;
|
return iv_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_nv_array_check_nocase(const nghttp2_nv *nva, size_t nvlen)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
for(i = 0; i < nvlen; ++i) {
|
|
||||||
if(!nghttp2_check_header_name_nocase(nva[i].name, nva[i].namelen)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(!nghttp2_check_header_value(nva[i].value, nva[i].valuelen)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nghttp2_nv_array_check(const nghttp2_nv *nva, size_t nvlen)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
for(i = 0; i < nvlen; ++i) {
|
|
||||||
if(!nghttp2_check_header_name(nva[i].name, nva[i].namelen)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(!nghttp2_check_header_value(nva[i].value, nva[i].valuelen)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nghttp2_nv_check(const uint8_t *name, size_t namelen,
|
|
||||||
const uint8_t *value, size_t valuelen)
|
|
||||||
{
|
|
||||||
if(!nghttp2_check_header_name(name, namelen)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(!nghttp2_check_header_value(value, valuelen)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nghttp2_nv_equal(const nghttp2_nv *a, const nghttp2_nv *b)
|
int nghttp2_nv_equal(const nghttp2_nv *a, const nghttp2_nv *b)
|
||||||
{
|
{
|
||||||
return a->namelen == b->namelen && a->valuelen == b->valuelen &&
|
return a->namelen == b->namelen && a->valuelen == b->valuelen &&
|
||||||
|
|
|
@ -558,25 +558,6 @@ int nghttp2_nv_equal(const nghttp2_nv *a, const nghttp2_nv *b);
|
||||||
*/
|
*/
|
||||||
void nghttp2_nv_array_del(nghttp2_nv *nva);
|
void nghttp2_nv_array_del(nghttp2_nv *nva);
|
||||||
|
|
||||||
/*
|
|
||||||
* Checks header name/value pair is well-formed. This function allows
|
|
||||||
* captital alphabet letters in name.
|
|
||||||
*
|
|
||||||
* This function returns nonzero if it succeeds, or 0.
|
|
||||||
*/
|
|
||||||
int nghttp2_nv_array_check_nocase(const nghttp2_nv *nva, size_t nvlen);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Checks header name/value pair is well-formed. This function does
|
|
||||||
* not allow captital alphabet letters in name.
|
|
||||||
*
|
|
||||||
* This function returns nonzero if it succeeds, or 0.
|
|
||||||
*/
|
|
||||||
int nghttp2_nv_array_check(const nghttp2_nv *nva, size_t nvlen);
|
|
||||||
|
|
||||||
int nghttp2_nv_check(const uint8_t *name, size_t namelen,
|
|
||||||
const uint8_t *value, size_t valuelen);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Checks that the |iv|, which includes |niv| entries, does not have
|
* Checks that the |iv|, which includes |niv| entries, does not have
|
||||||
* invalid values. The |flow_control_opt| is current flow control
|
* invalid values. The |flow_control_opt| is current flow control
|
||||||
|
|
|
@ -154,183 +154,6 @@ int nghttp2_should_send_window_update(int32_t local_window_size,
|
||||||
return recv_window_size >= local_window_size / 2;
|
return recv_window_size >= local_window_size / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int VALID_HD_NAME_CHARS[] = {
|
|
||||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
|
||||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
|
||||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
|
||||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
|
||||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
|
||||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
|
||||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
|
||||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
|
||||||
0 /* SPC */, 1 /* ! */, 0 /* " */, 1 /* # */,
|
|
||||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
|
||||||
0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */,
|
|
||||||
0 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
|
||||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
|
||||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
|
||||||
1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
|
|
||||||
0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */,
|
|
||||||
0 /* @ */, 0 /* A */, 0 /* B */, 0 /* C */,
|
|
||||||
0 /* D */, 0 /* E */, 0 /* F */, 0 /* G */,
|
|
||||||
0 /* H */, 0 /* I */, 0 /* J */, 0 /* K */,
|
|
||||||
0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */,
|
|
||||||
0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */,
|
|
||||||
0 /* T */, 0 /* U */, 0 /* V */, 0 /* W */,
|
|
||||||
0 /* X */, 0 /* Y */, 0 /* Z */, 0 /* [ */,
|
|
||||||
0 /* \ */, 0 /* ] */, 1 /* ^ */, 1 /* _ */,
|
|
||||||
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
|
||||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
|
||||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
|
||||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
|
||||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
|
||||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
|
||||||
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
|
||||||
1 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
|
||||||
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
|
||||||
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
|
||||||
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
|
||||||
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
|
||||||
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
|
||||||
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
|
||||||
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
|
||||||
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
|
||||||
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
|
||||||
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
|
||||||
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
|
||||||
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
|
||||||
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
|
||||||
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
|
||||||
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
|
||||||
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
|
||||||
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
|
||||||
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
|
||||||
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
|
||||||
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
|
||||||
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
|
||||||
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
|
||||||
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
|
||||||
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
|
||||||
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
|
||||||
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
|
||||||
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
|
||||||
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
|
||||||
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
|
||||||
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
|
||||||
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
|
||||||
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
|
||||||
};
|
|
||||||
|
|
||||||
static int check_header_name(const uint8_t *name, size_t len, int nocase)
|
|
||||||
{
|
|
||||||
const uint8_t *last;
|
|
||||||
if(len == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(*name == ':') {
|
|
||||||
if(len == 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
++name;
|
|
||||||
--len;
|
|
||||||
}
|
|
||||||
for(last = name + len; name != last; ++name) {
|
|
||||||
if(nocase && 'A' <= *name && *name <= 'Z') continue;
|
|
||||||
if(!VALID_HD_NAME_CHARS[*name]) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nghttp2_check_header_name(const uint8_t *name, size_t len)
|
|
||||||
{
|
|
||||||
return check_header_name(name, len, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int nghttp2_check_header_name_nocase(const uint8_t *name, size_t len)
|
|
||||||
{
|
|
||||||
return check_header_name(name, len, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int VALID_HD_VALUE_CHARS[] = {
|
|
||||||
1 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
|
||||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
|
||||||
0 /* BS */, 1 /* HT */, 0 /* LF */, 0 /* VT */,
|
|
||||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
|
||||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
|
||||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
|
||||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
|
||||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
|
||||||
1 /* SPC */, 1 /* ! */, 1 /* " */, 1 /* # */,
|
|
||||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
|
||||||
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
|
||||||
1 /* , */, 1 /* - */, 1 /* . */, 1 /* / */,
|
|
||||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
|
||||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
|
||||||
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
|
||||||
1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */,
|
|
||||||
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
|
||||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
|
||||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
|
||||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
|
||||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
|
||||||
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
|
||||||
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
|
||||||
1 /* \ */, 1 /* ] */, 1 /* ^ */, 1 /* _ */,
|
|
||||||
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
|
||||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
|
||||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
|
||||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
|
||||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
|
||||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
|
||||||
1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */,
|
|
||||||
1 /* | */, 1 /* } */, 1 /* ~ */, 0 /* DEL */,
|
|
||||||
1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
|
|
||||||
1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
|
|
||||||
1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
|
|
||||||
1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
|
|
||||||
1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
|
|
||||||
1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
|
|
||||||
1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
|
|
||||||
1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
|
|
||||||
1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
|
|
||||||
1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
|
|
||||||
1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
|
|
||||||
1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
|
|
||||||
1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
|
|
||||||
1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
|
|
||||||
1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
|
|
||||||
1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
|
|
||||||
1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
|
|
||||||
1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
|
|
||||||
1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
|
|
||||||
1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
|
|
||||||
1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
|
|
||||||
1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
|
|
||||||
1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
|
|
||||||
1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
|
|
||||||
1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
|
|
||||||
1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
|
|
||||||
1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
|
|
||||||
1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
|
|
||||||
1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
|
|
||||||
1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
|
|
||||||
1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
|
|
||||||
1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
|
|
||||||
};
|
|
||||||
|
|
||||||
int nghttp2_check_header_value(const uint8_t* value, size_t len)
|
|
||||||
{
|
|
||||||
const uint8_t *last;
|
|
||||||
for(last = value + len; value != last; ++value) {
|
|
||||||
if(!VALID_HD_VALUE_CHARS[*value]) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* nghttp2_strerror(int error_code)
|
const char* nghttp2_strerror(int error_code)
|
||||||
{
|
{
|
||||||
switch(error_code) {
|
switch(error_code) {
|
||||||
|
|
|
@ -118,28 +118,6 @@ int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
|
||||||
int nghttp2_should_send_window_update(int32_t local_window_size,
|
int nghttp2_should_send_window_update(int32_t local_window_size,
|
||||||
int32_t recv_window_size);
|
int32_t recv_window_size);
|
||||||
|
|
||||||
/*
|
|
||||||
* Checks the header name in |name| with |len| bytes is well-formed.
|
|
||||||
*
|
|
||||||
* This function returns nonzero if it succeeds, or 0.
|
|
||||||
*/
|
|
||||||
int nghttp2_check_header_name(const uint8_t *name, size_t len);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Checks the header name in |name| with |len| bytes is
|
|
||||||
* well-formed. This function accepts also characters in [A-Z].
|
|
||||||
*
|
|
||||||
* This function returns nonzero if it succeeds, or 0.
|
|
||||||
*/
|
|
||||||
int nghttp2_check_header_name_nocase(const uint8_t *name, size_t len);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Checks the header value in |value| with |len| bytes is well-formed.
|
|
||||||
*
|
|
||||||
* This function returns nonzero if it succeeds, or 0.
|
|
||||||
*/
|
|
||||||
int nghttp2_check_header_value(const uint8_t* value, size_t len);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deallocates memory space pointed by |ptr|. This function exists for
|
* Deallocates memory space pointed by |ptr|. This function exists for
|
||||||
* the application to free the memory space allocated by the library
|
* the application to free the memory space allocated by the library
|
||||||
|
|
|
@ -110,9 +110,6 @@ static int nghttp2_submit_headers_shared_nva
|
||||||
{
|
{
|
||||||
ssize_t rv;
|
ssize_t rv;
|
||||||
nghttp2_nv *nva_copy;
|
nghttp2_nv *nva_copy;
|
||||||
if(!nghttp2_nv_array_check_nocase(nva, nvlen)) {
|
|
||||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen);
|
rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen);
|
||||||
if(rv < 0) {
|
if(rv < 0) {
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -195,12 +192,6 @@ int nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
|
||||||
uint8_t flags_copy;
|
uint8_t flags_copy;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
if(!nghttp2_nv_array_check_nocase(nva, nvlen)) {
|
|
||||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
if(nghttp2_session_get_stream(session, stream_id) == NULL) {
|
|
||||||
return NGHTTP2_ERR_STREAM_CLOSED;
|
|
||||||
}
|
|
||||||
frame = malloc(sizeof(nghttp2_frame));
|
frame = malloc(sizeof(nghttp2_frame));
|
||||||
if(frame == NULL) {
|
if(frame == NULL) {
|
||||||
return NGHTTP2_ERR_NOMEM;
|
return NGHTTP2_ERR_NOMEM;
|
||||||
|
|
|
@ -791,6 +791,9 @@ int on_header_callback(nghttp2_session *session,
|
||||||
if(!stream) {
|
if(!stream) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if(!http2::check_nv(name, namelen, value, valuelen)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
http2::split_add_header(stream->headers, name, namelen, value, valuelen);
|
http2::split_add_header(stream->headers, name, namelen, value, valuelen);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
201
src/http2.cc
201
src/http2.cc
|
@ -90,7 +90,7 @@ void capitalize(std::string& s, size_t offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_header_value(const char *value)
|
bool lws(const char *value)
|
||||||
{
|
{
|
||||||
for(; *value; ++value) {
|
for(; *value; ++value) {
|
||||||
switch(*value) {
|
switch(*value) {
|
||||||
|
@ -98,10 +98,10 @@ bool check_header_value(const char *value)
|
||||||
case ' ':
|
case ' ':
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sanitize_header_value(std::string& s, size_t offset)
|
void sanitize_header_value(std::string& s, size_t offset)
|
||||||
|
@ -535,6 +535,201 @@ std::string rewrite_location_uri(const std::string& uri,
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int VALID_HD_NAME_CHARS[] = {
|
||||||
|
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||||
|
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||||
|
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||||
|
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||||
|
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||||
|
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||||
|
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||||
|
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||||
|
0 /* SPC */, 1 /* ! */, 0 /* " */, 1 /* # */,
|
||||||
|
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||||
|
0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */,
|
||||||
|
0 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
||||||
|
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||||
|
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||||
|
1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
|
||||||
|
0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */,
|
||||||
|
0 /* @ */, 0 /* A */, 0 /* B */, 0 /* C */,
|
||||||
|
0 /* D */, 0 /* E */, 0 /* F */, 0 /* G */,
|
||||||
|
0 /* H */, 0 /* I */, 0 /* J */, 0 /* K */,
|
||||||
|
0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */,
|
||||||
|
0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */,
|
||||||
|
0 /* T */, 0 /* U */, 0 /* V */, 0 /* W */,
|
||||||
|
0 /* X */, 0 /* Y */, 0 /* Z */, 0 /* [ */,
|
||||||
|
0 /* \ */, 0 /* ] */, 1 /* ^ */, 1 /* _ */,
|
||||||
|
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||||
|
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||||
|
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||||
|
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||||
|
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||||
|
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||||
|
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
||||||
|
1 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||||
|
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
||||||
|
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
||||||
|
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
||||||
|
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
||||||
|
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
||||||
|
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
||||||
|
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
||||||
|
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
||||||
|
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
||||||
|
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
||||||
|
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
||||||
|
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
||||||
|
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
||||||
|
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
||||||
|
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
||||||
|
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
||||||
|
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
||||||
|
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
||||||
|
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
||||||
|
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
||||||
|
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
||||||
|
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
||||||
|
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
||||||
|
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
||||||
|
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
||||||
|
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
||||||
|
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
||||||
|
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
||||||
|
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
||||||
|
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
||||||
|
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
||||||
|
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int check_header_name(const uint8_t *name, size_t len, int nocase)
|
||||||
|
{
|
||||||
|
const uint8_t *last;
|
||||||
|
if(len == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(*name == ':') {
|
||||||
|
if(len == 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
++name;
|
||||||
|
--len;
|
||||||
|
}
|
||||||
|
for(last = name + len; name != last; ++name) {
|
||||||
|
if(nocase && 'A' <= *name && *name <= 'Z') continue;
|
||||||
|
if(!VALID_HD_NAME_CHARS[*name]) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int check_header_name(const uint8_t *name, size_t len)
|
||||||
|
{
|
||||||
|
return check_header_name(name, len, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int check_header_name_nocase(const uint8_t *name, size_t len)
|
||||||
|
{
|
||||||
|
return check_header_name(name, len, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int VALID_HD_VALUE_CHARS[] = {
|
||||||
|
1 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||||
|
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||||
|
0 /* BS */, 1 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||||
|
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||||
|
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||||
|
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||||
|
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||||
|
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||||
|
1 /* SPC */, 1 /* ! */, 1 /* " */, 1 /* # */,
|
||||||
|
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||||
|
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
||||||
|
1 /* , */, 1 /* - */, 1 /* . */, 1 /* / */,
|
||||||
|
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||||
|
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||||
|
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
||||||
|
1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */,
|
||||||
|
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||||
|
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||||
|
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||||
|
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||||
|
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
||||||
|
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
||||||
|
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
||||||
|
1 /* \ */, 1 /* ] */, 1 /* ^ */, 1 /* _ */,
|
||||||
|
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||||
|
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||||
|
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||||
|
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||||
|
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||||
|
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||||
|
1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */,
|
||||||
|
1 /* | */, 1 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||||
|
1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
|
||||||
|
1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
|
||||||
|
1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
|
||||||
|
1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
|
||||||
|
1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
|
||||||
|
1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
|
||||||
|
1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
|
||||||
|
1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
|
||||||
|
1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
|
||||||
|
1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
|
||||||
|
1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
|
||||||
|
1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
|
||||||
|
1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
|
||||||
|
1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
|
||||||
|
1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
|
||||||
|
1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
|
||||||
|
1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
|
||||||
|
1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
|
||||||
|
1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
|
||||||
|
1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
|
||||||
|
1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
|
||||||
|
1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
|
||||||
|
1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
|
||||||
|
1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
|
||||||
|
1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
|
||||||
|
1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
|
||||||
|
1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
|
||||||
|
1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
|
||||||
|
1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
|
||||||
|
1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
|
||||||
|
1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
|
||||||
|
1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int check_header_value(const uint8_t* value, size_t len)
|
||||||
|
{
|
||||||
|
const uint8_t *last;
|
||||||
|
for(last = value + len; value != last; ++value) {
|
||||||
|
if(!VALID_HD_VALUE_CHARS[*value]) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int check_nv(const uint8_t *name, size_t namelen,
|
||||||
|
const uint8_t *value, size_t valuelen)
|
||||||
|
{
|
||||||
|
if(!check_header_name(name, namelen)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!check_header_value(value, valuelen)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace http2
|
} // namespace http2
|
||||||
|
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|
28
src/http2.h
28
src/http2.h
|
@ -46,8 +46,8 @@ std::string get_status_string(unsigned int status_code);
|
||||||
|
|
||||||
void capitalize(std::string& s, size_t offset);
|
void capitalize(std::string& s, size_t offset);
|
||||||
|
|
||||||
// Returns false if |value| is LWS
|
// Returns true if |value| is LWS
|
||||||
bool check_header_value(const char *value);
|
bool lws(const char *value);
|
||||||
|
|
||||||
void sanitize_header_value(std::string& s, size_t offset);
|
void sanitize_header_value(std::string& s, size_t offset);
|
||||||
|
|
||||||
|
@ -197,6 +197,30 @@ std::string rewrite_location_uri(const std::string& uri,
|
||||||
const std::string& upstream_scheme,
|
const std::string& upstream_scheme,
|
||||||
uint16_t upstream_port);
|
uint16_t upstream_port);
|
||||||
|
|
||||||
|
|
||||||
|
// Checks the header name in |name| with |len| bytes is well-formed.
|
||||||
|
//
|
||||||
|
// This function returns nonzero if it succeeds, or 0.
|
||||||
|
int check_header_name(const uint8_t *name, size_t len);
|
||||||
|
|
||||||
|
|
||||||
|
// Checks the header name in |name| with |len| bytes is
|
||||||
|
// well-formed. This function accepts also characters in [A-Z].
|
||||||
|
//
|
||||||
|
// This function returns nonzero if it succeeds, or 0.
|
||||||
|
int check_header_name_nocase(const uint8_t *name, size_t len);
|
||||||
|
|
||||||
|
// Checks the header value in |value| with |len| bytes is well-formed.
|
||||||
|
//
|
||||||
|
// This function returns nonzero if it succeeds, or 0.
|
||||||
|
int check_header_value(const uint8_t* value, size_t len);
|
||||||
|
|
||||||
|
// Checks the header name/value pair using check_header_name() and
|
||||||
|
// check_header_value(). If both function returns nonzero, this
|
||||||
|
// function returns nonzero.
|
||||||
|
int check_nv(const uint8_t *name, size_t namelen,
|
||||||
|
const uint8_t *value, size_t valuelen);
|
||||||
|
|
||||||
} // namespace http2
|
} // namespace http2
|
||||||
|
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|
|
@ -244,11 +244,11 @@ void test_http2_build_http1_headers_from_norm_headers(void)
|
||||||
// CU_ASSERT(hdrs == "Alpha: bravo charlie \r\n");
|
// CU_ASSERT(hdrs == "Alpha: bravo charlie \r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_http2_check_header_value(void)
|
void test_http2_lws(void)
|
||||||
{
|
{
|
||||||
CU_ASSERT(http2::check_header_value("alpha"));
|
CU_ASSERT(!http2::lws("alpha"));
|
||||||
CU_ASSERT(!http2::check_header_value(" "));
|
CU_ASSERT(http2::lws(" "));
|
||||||
CU_ASSERT(!http2::check_header_value(""));
|
CU_ASSERT(http2::lws(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -297,4 +297,52 @@ void test_http2_rewrite_location_uri(void)
|
||||||
"localhost", "https", 3000);
|
"localhost", "https", 3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int check_header_name(const char *s)
|
||||||
|
{
|
||||||
|
return http2::check_header_name((const uint8_t*)s, strlen(s));
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int check_header_name_nocase(const char *s)
|
||||||
|
{
|
||||||
|
return http2::check_header_name_nocase((const uint8_t*)s, strlen(s));
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void test_http2_check_header_name(void)
|
||||||
|
{
|
||||||
|
CU_ASSERT(check_header_name(":path"));
|
||||||
|
CU_ASSERT(check_header_name("path"));
|
||||||
|
CU_ASSERT(check_header_name("!#$%&'*+-.^_`|~"));
|
||||||
|
CU_ASSERT(!check_header_name(":PATH"));
|
||||||
|
CU_ASSERT(!check_header_name("path:"));
|
||||||
|
CU_ASSERT(!check_header_name(""));
|
||||||
|
CU_ASSERT(!check_header_name(":"));
|
||||||
|
|
||||||
|
CU_ASSERT(check_header_name_nocase(":path"));
|
||||||
|
CU_ASSERT(check_header_name_nocase("path"));
|
||||||
|
CU_ASSERT(check_header_name_nocase("!#$%&'*+-.^_`|~"));
|
||||||
|
CU_ASSERT(check_header_name_nocase(":PATH"));
|
||||||
|
CU_ASSERT(!check_header_name_nocase("path:"));
|
||||||
|
CU_ASSERT(!check_header_name_nocase(""));
|
||||||
|
CU_ASSERT(!check_header_name_nocase(":"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define check_header_value(S) \
|
||||||
|
http2::check_header_value((const uint8_t*)S, sizeof(S) - 1)
|
||||||
|
|
||||||
|
void test_http2_check_header_value(void)
|
||||||
|
{
|
||||||
|
uint8_t goodval[] = { 'a', '\0', 'b', 0x80u, 'c', 0xffu, 'd', '\t', ' ' };
|
||||||
|
uint8_t badval1[] = { 'a', 0x1fu, 'b' };
|
||||||
|
uint8_t badval2[] = { 'a', 0x7fu, 'b' };
|
||||||
|
|
||||||
|
CU_ASSERT(check_header_value(" !|}~"));
|
||||||
|
CU_ASSERT(check_header_value(goodval));
|
||||||
|
CU_ASSERT(!check_header_value(badval1));
|
||||||
|
CU_ASSERT(!check_header_value(badval2));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -36,8 +36,10 @@ void test_http2_value_lws(void);
|
||||||
void test_http2_concat_norm_headers(void);
|
void test_http2_concat_norm_headers(void);
|
||||||
void test_http2_copy_norm_headers_to_nva(void);
|
void test_http2_copy_norm_headers_to_nva(void);
|
||||||
void test_http2_build_http1_headers_from_norm_headers(void);
|
void test_http2_build_http1_headers_from_norm_headers(void);
|
||||||
void test_http2_check_header_value(void);
|
void test_http2_lws(void);
|
||||||
void test_http2_rewrite_location_uri(void);
|
void test_http2_rewrite_location_uri(void);
|
||||||
|
void test_http2_check_header_name(void);
|
||||||
|
void test_http2_check_header_value(void);
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
||||||
|
|
|
@ -87,10 +87,14 @@ int main(int argc, char* argv[])
|
||||||
shrpx::test_http2_copy_norm_headers_to_nva) ||
|
shrpx::test_http2_copy_norm_headers_to_nva) ||
|
||||||
!CU_add_test(pSuite, "http2_build_http1_headers_from_norm_headers",
|
!CU_add_test(pSuite, "http2_build_http1_headers_from_norm_headers",
|
||||||
shrpx::test_http2_build_http1_headers_from_norm_headers) ||
|
shrpx::test_http2_build_http1_headers_from_norm_headers) ||
|
||||||
!CU_add_test(pSuite, "http2_check_header_value",
|
!CU_add_test(pSuite, "http2_lws",
|
||||||
shrpx::test_http2_check_header_value) ||
|
shrpx::test_http2_lws) ||
|
||||||
!CU_add_test(pSuite, "http2_rewrite_location_uri",
|
!CU_add_test(pSuite, "http2_rewrite_location_uri",
|
||||||
shrpx::test_http2_rewrite_location_uri) ||
|
shrpx::test_http2_rewrite_location_uri) ||
|
||||||
|
!CU_add_test(pSuite, "http2_check_header_name",
|
||||||
|
shrpx::test_http2_check_header_name) ||
|
||||||
|
!CU_add_test(pSuite, "http2_check_header_value",
|
||||||
|
shrpx::test_http2_check_header_value) ||
|
||||||
!CU_add_test(pSuite, "downstream_normalize_request_headers",
|
!CU_add_test(pSuite, "downstream_normalize_request_headers",
|
||||||
shrpx::test_downstream_normalize_request_headers) ||
|
shrpx::test_downstream_normalize_request_headers) ||
|
||||||
!CU_add_test(pSuite, "downstream_normalize_response_headers",
|
!CU_add_test(pSuite, "downstream_normalize_response_headers",
|
||||||
|
|
|
@ -816,7 +816,9 @@ int on_header_callback(nghttp2_session *session,
|
||||||
if(!downstream) {
|
if(!downstream) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// TODO Discard malformed header here
|
if(!http2::check_nv(name, namelen, value, valuelen)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
downstream->split_add_response_header(name, namelen, value, valuelen);
|
downstream->split_add_response_header(name, namelen, value, valuelen);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,7 +233,9 @@ int on_header_callback(nghttp2_session *session,
|
||||||
if(!downstream) {
|
if(!downstream) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// TODO Discard malformed header here
|
if(!http2::check_nv(name, namelen, value, valuelen)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
downstream->split_add_request_header(name, namelen, value, valuelen);
|
downstream->split_add_request_header(name, namelen, value, valuelen);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,10 +179,8 @@ void on_ctrl_recv_callback
|
||||||
}
|
}
|
||||||
bool is_connect = method && strcmp("CONNECT", method) == 0;
|
bool is_connect = method && strcmp("CONNECT", method) == 0;
|
||||||
if(!path || !host || !method ||
|
if(!path || !host || !method ||
|
||||||
!http2::check_header_value(host) ||
|
http2::lws(host) || http2::lws(path) || http2::lws(method) ||
|
||||||
!http2::check_header_value(path) ||
|
(!is_connect && (!scheme || http2::lws(scheme)))) {
|
||||||
!http2::check_header_value(method) ||
|
|
||||||
(!is_connect && (!scheme || !http2::check_header_value(scheme)))) {
|
|
||||||
upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR);
|
upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,8 +215,6 @@ int main(int argc, char* argv[])
|
||||||
test_nghttp2_frame_pack_goaway) ||
|
test_nghttp2_frame_pack_goaway) ||
|
||||||
!CU_add_test(pSuite, "frame_pack_window_update",
|
!CU_add_test(pSuite, "frame_pack_window_update",
|
||||||
test_nghttp2_frame_pack_window_update) ||
|
test_nghttp2_frame_pack_window_update) ||
|
||||||
!CU_add_test(pSuite, "nv_array_check",
|
|
||||||
test_nghttp2_nv_array_check) ||
|
|
||||||
!CU_add_test(pSuite, "nv_array_copy", test_nghttp2_nv_array_copy) ||
|
!CU_add_test(pSuite, "nv_array_copy", test_nghttp2_nv_array_copy) ||
|
||||||
!CU_add_test(pSuite, "iv_check", test_nghttp2_iv_check) ||
|
!CU_add_test(pSuite, "iv_check", test_nghttp2_iv_check) ||
|
||||||
!CU_add_test(pSuite, "hd_deflate", test_nghttp2_hd_deflate) ||
|
!CU_add_test(pSuite, "hd_deflate", test_nghttp2_hd_deflate) ||
|
||||||
|
@ -248,11 +246,7 @@ int main(int argc, char* argv[])
|
||||||
test_nghttp2_hd_deflate_inflate) ||
|
test_nghttp2_hd_deflate_inflate) ||
|
||||||
!CU_add_test(pSuite, "gzip_inflate", test_nghttp2_gzip_inflate) ||
|
!CU_add_test(pSuite, "gzip_inflate", test_nghttp2_gzip_inflate) ||
|
||||||
!CU_add_test(pSuite, "adjust_local_window_size",
|
!CU_add_test(pSuite, "adjust_local_window_size",
|
||||||
test_nghttp2_adjust_local_window_size) ||
|
test_nghttp2_adjust_local_window_size)
|
||||||
!CU_add_test(pSuite, "check_header_name",
|
|
||||||
test_nghttp2_check_header_name) ||
|
|
||||||
!CU_add_test(pSuite, "check_header_value",
|
|
||||||
test_nghttp2_check_header_value)
|
|
||||||
) {
|
) {
|
||||||
CU_cleanup_registry();
|
CU_cleanup_registry();
|
||||||
return CU_get_error();
|
return CU_get_error();
|
||||||
|
|
|
@ -370,39 +370,6 @@ void test_nghttp2_frame_pack_window_update(void)
|
||||||
nghttp2_frame_window_update_free(&frame);
|
nghttp2_frame_window_update_free(&frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_nghttp2_nv_array_check(void)
|
|
||||||
{
|
|
||||||
nghttp2_nv nva1[] = {MAKE_NV("path", "/"),
|
|
||||||
MAKE_NV("host", "a")};
|
|
||||||
nghttp2_nv nva2[] = {MAKE_NV("", "/"),
|
|
||||||
MAKE_NV("host", "a")};
|
|
||||||
nghttp2_nv nva3[] = {MAKE_NV("path", "/"),
|
|
||||||
MAKE_NV("host\x01", "a")};
|
|
||||||
nghttp2_nv nva4[] = {MAKE_NV("PATH", "/")};
|
|
||||||
nghttp2_nv nva5[] = {MAKE_NV("path", "foo"),
|
|
||||||
MAKE_NV("host", "foo\x00")};
|
|
||||||
nghttp2_nv nva6[] = {MAKE_NV("path", "foo"),
|
|
||||||
MAKE_NV("host", "foo\x01")};
|
|
||||||
|
|
||||||
CU_ASSERT(nghttp2_nv_array_check(nva1, ARRLEN(nva1)));
|
|
||||||
CU_ASSERT(nghttp2_nv_array_check_nocase(nva1, ARRLEN(nva1)));
|
|
||||||
|
|
||||||
CU_ASSERT(0 == nghttp2_nv_array_check(nva2, ARRLEN(nva2)));
|
|
||||||
CU_ASSERT(0 == nghttp2_nv_array_check_nocase(nva2, ARRLEN(nva2)));
|
|
||||||
|
|
||||||
CU_ASSERT(0 == nghttp2_nv_array_check(nva3, ARRLEN(nva3)));
|
|
||||||
CU_ASSERT(0 == nghttp2_nv_array_check_nocase(nva3, ARRLEN(nva3)));
|
|
||||||
|
|
||||||
CU_ASSERT(0 == nghttp2_nv_array_check(nva4, ARRLEN(nva4)));
|
|
||||||
CU_ASSERT(nghttp2_nv_array_check_nocase(nva4, ARRLEN(nva4)));
|
|
||||||
|
|
||||||
CU_ASSERT(nghttp2_nv_array_check(nva5, ARRLEN(nva5)));
|
|
||||||
CU_ASSERT(nghttp2_nv_array_check_nocase(nva5, ARRLEN(nva5)));
|
|
||||||
|
|
||||||
CU_ASSERT(0 == nghttp2_nv_array_check(nva6, ARRLEN(nva6)));
|
|
||||||
CU_ASSERT(0 == nghttp2_nv_array_check_nocase(nva6, ARRLEN(nva6)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_nghttp2_nv_array_copy(void)
|
void test_nghttp2_nv_array_copy(void)
|
||||||
{
|
{
|
||||||
nghttp2_nv *nva;
|
nghttp2_nv *nva;
|
||||||
|
|
|
@ -34,7 +34,6 @@ void test_nghttp2_frame_pack_push_promise(void);
|
||||||
void test_nghttp2_frame_pack_ping(void);
|
void test_nghttp2_frame_pack_ping(void);
|
||||||
void test_nghttp2_frame_pack_goaway(void);
|
void test_nghttp2_frame_pack_goaway(void);
|
||||||
void test_nghttp2_frame_pack_window_update(void);
|
void test_nghttp2_frame_pack_window_update(void);
|
||||||
void test_nghttp2_nv_array_check(void);
|
|
||||||
void test_nghttp2_nv_array_copy(void);
|
void test_nghttp2_nv_array_copy(void);
|
||||||
void test_nghttp2_iv_check(void);
|
void test_nghttp2_iv_check(void);
|
||||||
|
|
||||||
|
|
|
@ -152,47 +152,3 @@ void test_nghttp2_adjust_local_window_size(void)
|
||||||
CU_ASSERT(0 == recv_reduction);
|
CU_ASSERT(0 == recv_reduction);
|
||||||
CU_ASSERT(INT32_MIN == delta);
|
CU_ASSERT(INT32_MIN == delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_header_name(const char *s)
|
|
||||||
{
|
|
||||||
return nghttp2_check_header_name((const uint8_t*)s, strlen(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int check_header_name_nocase(const char *s)
|
|
||||||
{
|
|
||||||
return nghttp2_check_header_name_nocase((const uint8_t*)s, strlen(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_nghttp2_check_header_name(void)
|
|
||||||
{
|
|
||||||
CU_ASSERT(check_header_name(":path"));
|
|
||||||
CU_ASSERT(check_header_name("path"));
|
|
||||||
CU_ASSERT(check_header_name("!#$%&'*+-.^_`|~"));
|
|
||||||
CU_ASSERT(!check_header_name(":PATH"));
|
|
||||||
CU_ASSERT(!check_header_name("path:"));
|
|
||||||
CU_ASSERT(!check_header_name(""));
|
|
||||||
CU_ASSERT(!check_header_name(":"));
|
|
||||||
|
|
||||||
CU_ASSERT(check_header_name_nocase(":path"));
|
|
||||||
CU_ASSERT(check_header_name_nocase("path"));
|
|
||||||
CU_ASSERT(check_header_name_nocase("!#$%&'*+-.^_`|~"));
|
|
||||||
CU_ASSERT(check_header_name_nocase(":PATH"));
|
|
||||||
CU_ASSERT(!check_header_name_nocase("path:"));
|
|
||||||
CU_ASSERT(!check_header_name_nocase(""));
|
|
||||||
CU_ASSERT(!check_header_name_nocase(":"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#define check_header_value(S) \
|
|
||||||
nghttp2_check_header_value((const uint8_t*)S, sizeof(S) - 1)
|
|
||||||
|
|
||||||
void test_nghttp2_check_header_value(void)
|
|
||||||
{
|
|
||||||
uint8_t goodval[] = { 'a', '\0', 'b', 0x80u, 'c', 0xffu, 'd', '\t', ' ' };
|
|
||||||
uint8_t badval1[] = { 'a', 0x1fu, 'b' };
|
|
||||||
uint8_t badval2[] = { 'a', 0x7fu, 'b' };
|
|
||||||
|
|
||||||
CU_ASSERT(check_header_value(" !|}~"));
|
|
||||||
CU_ASSERT(check_header_value(goodval));
|
|
||||||
CU_ASSERT(!check_header_value(badval1));
|
|
||||||
CU_ASSERT(!check_header_value(badval2));
|
|
||||||
}
|
|
||||||
|
|
|
@ -26,7 +26,5 @@
|
||||||
#define NGHTTP2_HELPER_TEST_H
|
#define NGHTTP2_HELPER_TEST_H
|
||||||
|
|
||||||
void test_nghttp2_adjust_local_window_size(void);
|
void test_nghttp2_adjust_local_window_size(void);
|
||||||
void test_nghttp2_check_header_name(void);
|
|
||||||
void test_nghttp2_check_header_value(void);
|
|
||||||
|
|
||||||
#endif /* NGHTTP2_HELPER_TEST_H */
|
#endif /* NGHTTP2_HELPER_TEST_H */
|
||||||
|
|
|
@ -2670,31 +2670,34 @@ void test_nghttp2_submit_invalid_nv(void)
|
||||||
MAKE_NV("", "empty name")
|
MAKE_NV("", "empty name")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Now invalid header name/value pair in HTTP/1.1 is accepted in
|
||||||
|
nghttp2 */
|
||||||
|
|
||||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||||
|
|
||||||
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
|
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
|
||||||
|
|
||||||
/* nghttp2_submit_request */
|
/* nghttp2_submit_request */
|
||||||
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
|
CU_ASSERT(0 ==
|
||||||
nghttp2_submit_request(session, NGHTTP2_PRI_DEFAULT,
|
nghttp2_submit_request(session, NGHTTP2_PRI_DEFAULT,
|
||||||
empty_name_nv, ARRLEN(empty_name_nv),
|
empty_name_nv, ARRLEN(empty_name_nv),
|
||||||
NULL, NULL));
|
NULL, NULL));
|
||||||
|
|
||||||
/* nghttp2_submit_response */
|
/* nghttp2_submit_response */
|
||||||
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
|
CU_ASSERT(0 ==
|
||||||
nghttp2_submit_response(session, 2,
|
nghttp2_submit_response(session, 2,
|
||||||
empty_name_nv, ARRLEN(empty_name_nv),
|
empty_name_nv, ARRLEN(empty_name_nv),
|
||||||
NULL));
|
NULL));
|
||||||
|
|
||||||
/* nghttp2_submit_headers */
|
/* nghttp2_submit_headers */
|
||||||
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
|
CU_ASSERT(0 ==
|
||||||
nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1,
|
nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1,
|
||||||
NGHTTP2_PRI_DEFAULT,
|
NGHTTP2_PRI_DEFAULT,
|
||||||
empty_name_nv, ARRLEN(empty_name_nv),
|
empty_name_nv, ARRLEN(empty_name_nv),
|
||||||
NULL));
|
NULL));
|
||||||
|
|
||||||
/* nghttp2_submit_push_promise */
|
/* nghttp2_submit_push_promise */
|
||||||
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
|
CU_ASSERT(0 ==
|
||||||
nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 2,
|
nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 2,
|
||||||
empty_name_nv, ARRLEN(empty_name_nv)));
|
empty_name_nv, ARRLEN(empty_name_nv)));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue