Check frame length after packing a frame

If resultant length of a frame exceeds the maximum value (which is
2**24 - 1 for SPDY/2 and 3), SPDYLAY_ERR_FRAME_TOO_LARGE is used to
indicate this error. This error will be notified by
on_ctrl_not_send_callback.
This commit is contained in:
Tatsuhiro Tsujikawa 2012-09-14 22:41:55 +09:00
parent 744f35e7ea
commit 088e4f15a2
8 changed files with 54 additions and 2 deletions

View File

@ -167,6 +167,10 @@ typedef enum {
* The user callback function failed due to the temporal error.
*/
SPDYLAY_ERR_TEMPORAL_CALLBACK_FAILURE = -521,
/**
* The length of the frame is too large.
*/
SPDYLAY_ERR_FRAME_TOO_LARGE = -522,
/**
* The errors < :enum:`SPDYLAY_ERR_FATAL` mean that the library is
* under unexpected condition and cannot process any further data

View File

@ -107,6 +107,11 @@ ssize_t spdylay_frame_alloc_pack_nv(uint8_t **buf_ptr,
return framelen;
}
framelen += nv_offset;
if(framelen - SPDYLAY_FRAME_HEAD_LENGTH > SPDYLAY_LENGTH_MASK) {
/* In SPDY/2 and 3, Max frame size is 2**24 - 1. */
return SPDYLAY_ERR_FRAME_TOO_LARGE;
}
return framelen;
}

View File

@ -35,6 +35,8 @@
#include "spdylay_client_cert_vector.h"
#define SPDYLAY_STREAM_ID_MASK 0x7fffffff
/* This is actually the maximum length of a control frame in SPDY/2
and 3. */
#define SPDYLAY_LENGTH_MASK 0xffffff
#define SPDYLAY_VERSION_MASK 0x7fff
#define SPDYLAY_DELTA_WINDOW_SIZE_MASK 0x7fffffff
@ -124,6 +126,8 @@ size_t spdylay_frame_get_len_size(uint16_t version);
* The version is not supported.
* SPDYLAY_ERR_ZLIB
* The deflate operation failed.
* SPDYLAY_ERR_FRAME_TOO_LARGE
* The length of the frame is too large.
* SPDYLAY_ERR_NOMEM
* Out of memory.
*/
@ -201,6 +205,8 @@ int spdylay_frame_unpack_syn_stream_without_nv(spdylay_syn_stream *frame,
* The version is not supported.
* SPDYLAY_ERR_ZLIB
* The deflate operation failed.
* SPDYLAY_ERR_FRAME_TOO_LARGE
* The length of the frame is too large.
* SPDYLAY_ERR_NOMEM
* Out of memory.
*/
@ -335,6 +341,8 @@ int spdylay_frame_unpack_goaway(spdylay_goaway *frame,
* The version is not supported.
* SPDYLAY_ERR_ZLIB
* The deflate operation failed.
* SPDYLAY_ERR_FRAME_TOO_LARGE
* The length of the frame is too large.
* SPDYLAY_ERR_NOMEM
* Out of memory.
*/
@ -539,6 +547,8 @@ ssize_t spdylay_frame_pack_nv(uint8_t *buf, char **nv, size_t len_size);
*
* SPDYLAY_ERR_ZLIB
* The deflate operation failed.
* SPDYLAY_ERR_FRAME_TOO_LARGE
* The length of the frame is too large.
* SPDYLAY_ERR_NOMEM
* Out of memory.
*/

View File

@ -119,6 +119,8 @@ const char* spdylay_strerror(int error_code)
return "Gzip error";
case SPDYLAY_ERR_TEMPORAL_CALLBACK_FAILURE:
return "The user callback function failed due to the temporal error";
case SPDYLAY_ERR_FRAME_TOO_LARGE:
return "The length of the frame is too large";
case SPDYLAY_ERR_NOMEM:
return "Out of memory";
case SPDYLAY_ERR_CALLBACK_FAILURE:

View File

@ -38,8 +38,7 @@ typedef int (*spdylay_compar)(const void *lhs, const void *rhs);
/* Internal error code. They must be in the range [-499, -100],
inclusive. */
typedef enum {
SPDYLAY_ERR_CREDENTIAL_PENDING = -101,
SPDYLAY_ERR_FRAME_TOO_LARGE = -102
SPDYLAY_ERR_CREDENTIAL_PENDING = -101
} spdylay_internal_error;
#endif /* SPDYLAY_INT_H */

View File

@ -186,6 +186,8 @@ int main(int argc, char* argv[])
test_spdylay_frame_pack_syn_stream_spdy2) ||
!CU_add_test(pSuite, "frame_pack_syn_stream_spdy3",
test_spdylay_frame_pack_syn_stream_spdy3) ||
!CU_add_test(pSuite, "frame_pack_syn_stream_frame_too_large",
test_spdylay_frame_pack_syn_stream_frame_too_large) ||
!CU_add_test(pSuite, "frame_pack_syn_reply_spdy2",
test_spdylay_frame_pack_syn_reply_spdy2) ||
!CU_add_test(pSuite, "frame_pack_syn_reply_spdy3",

View File

@ -346,6 +346,35 @@ void test_spdylay_frame_pack_syn_stream_spdy3(void)
test_spdylay_frame_pack_syn_stream_version(SPDYLAY_PROTO_SPDY3);
}
void test_spdylay_frame_pack_syn_stream_frame_too_large(void)
{
spdylay_zlib deflater;
spdylay_frame frame;
uint8_t *buf = NULL, *nvbuf = NULL;
size_t buflen = 0, nvbuflen = 0;
ssize_t framelen;
size_t big_vallen = 16777215;
char *big_val = malloc(big_vallen + 1);
const char *big_hds[] = { "header", big_val, NULL };
memset(big_val, '0', big_vallen);
big_val[big_vallen] = '\0';
spdylay_zlib_deflate_hd_init(&deflater, SPDYLAY_PROTO_SPDY3);
spdylay_frame_syn_stream_init(&frame.syn_stream, SPDYLAY_PROTO_SPDY3,
SPDYLAY_CTRL_FLAG_FIN, 65536, 1000000007, 3,
spdylay_frame_nv_copy(big_hds));
framelen = spdylay_frame_pack_syn_stream(&buf, &buflen,
&nvbuf, &nvbuflen,
&frame.syn_stream, &deflater);
CU_ASSERT_EQUAL(SPDYLAY_ERR_FRAME_TOO_LARGE, framelen);
spdylay_frame_syn_stream_free(&frame.syn_stream);
free(buf);
free(nvbuf);
free(big_val);
spdylay_zlib_deflate_free(&deflater);
}
static void test_spdylay_frame_pack_syn_reply_version(uint16_t version)
{
spdylay_zlib deflater, inflater;

View File

@ -35,6 +35,7 @@ void test_spdylay_frame_pack_goaway_spdy2(void);
void test_spdylay_frame_pack_goaway_spdy3(void);
void test_spdylay_frame_pack_syn_stream_spdy2(void);
void test_spdylay_frame_pack_syn_stream_spdy3(void);
void test_spdylay_frame_pack_syn_stream_frame_too_large(void);
void test_spdylay_frame_pack_syn_reply_spdy2(void);
void test_spdylay_frame_pack_syn_reply_spdy3(void);
void test_spdylay_frame_pack_headers_spdy2(void);