diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | cl-parser.c | 150 | ||||
-rw-r--r-- | error.c | 10 | ||||
-rw-r--r-- | include/fhp/fhp.h | 25 |
4 files changed, 184 insertions, 3 deletions
@@ -1,6 +1,6 @@ CC ?= cc CFLAGS=-std=c99 -W -Wall -pedantic -O2 -Iinclude -fPIC -OBJS=fhp.o hash.o error.o token.o env.o te-parser.o header-value-parser.o +OBJS=fhp.o hash.o error.o token.o env.o te-parser.o cl-parser.o header-value-parser.o SONAME=libfhp.so LIB=libfhp.so STATIC_LIB=libfhp.a diff --git a/cl-parser.c b/cl-parser.c new file mode 100644 index 0000000..83863c5 --- /dev/null +++ b/cl-parser.c @@ -0,0 +1,150 @@ +#include "internal.h" + +// +// content length functions +// + +static const fhp_cl_parser_t FHP_DEFAULT_CL_PARSER = { + .state = FHP_CL_STATE_INIT, + .val = 0, + .err = FHP_OK, +}; + +fhp_err_t +fhp_cl_parser_init(fhp_cl_parser_t * const p) { + // init parser + *p = FHP_DEFAULT_CL_PARSER; + + // return succes + return FHP_OK; +} + +static fhp_err_t +fhp_cl_parser_push_byte( + fhp_cl_parser_t * const p, + uint8_t byte +) { +retry: + switch (p->state) { + case FHP_CL_STATE_INIT: + switch (byte) { + CASE_OWS_CHARS + // ignore + break; + CASE_DIGIT_CHARS + // set state + p->state = FHP_CL_STATE_DATA; + goto retry; + + break; + default: + // invalid character before content-length + return FHP_ERR_INVALID_CHAR_BEFORE_CL; + } + + break; + case FHP_CL_STATE_DATA: + switch (byte) { + CASE_OWS_CHARS + // set state + p->state = FHP_CL_STATE_TRAILING_SPACES; + goto retry; + + break; + CASE_DIGIT_CHARS + { + // cache old value + uint64_t old_val = p->val; + + // update value + p->val = p->val * 10 + (byte - '0'); + + // check for overflow + if (p->val < old_val) + return FHP_ERR_CL_OVERFLOW; + } + + break; + default: + // invalid character in content-length + return FHP_ERR_INVALID_CHAR_IN_CL; + } + + break; + case FHP_CL_STATE_TRAILING_SPACES: + switch (byte) { + CASE_OWS_CHARS + // ignore trailing spaces + + break; + default: + // invalid character after content-length + return FHP_ERR_INVALID_CHAR_AFTER_CL; + } + + break; + case FHP_CL_STATE_ERROR: + // return last error + return p->err; + + break; + case FHP_CL_STATE_DONE: + // shouldn't be reached + return FHP_ERR_CL_PARSER_DONE; + + break; + default: + // never reached + return FHP_ERR_BAD_CL_STATE; + } + + // return succes + return FHP_OK; +} + +fhp_err_t +fhp_cl_parser_push( + fhp_cl_parser_t *p, + uint8_t * const buf, + size_t len +) { + for (size_t i = 0; i < len; i++) { + // push byte + fhp_err_t err = fhp_cl_parser_push_byte(p, buf[i]); + + // check error + if (err != FHP_OK) { + // cache error + p->err = err; + + // set state + p->state = FHP_CL_STATE_ERROR; + + // return error + return err; + } + } + + // return succes + return FHP_OK; +} + +fhp_err_t +fhp_cl_parser_done( + fhp_cl_parser_t * const p, + uint64_t * const ret_val +) { + // check for error + if (p->err != FHP_OK) + return p->err; + + // set state + p->state = FHP_TE_STATE_DONE; + + // save number of tes + if (ret_val) + *ret_val = p->val; + + // return success + return FHP_OK; +} @@ -22,10 +22,16 @@ fhp_errors[] = { "too many transfer encodings", "invalid character in transfer encoding name", "invalid character in transfer encoding", - "bad transfer encoding state", - "transfer encoding parser already done", + "bad transfer-encoding parser state", + "transfer-encoding parser already done", "NULL transfer encoding hash output buffer", "transfer encoding hash output buffer is too small", + "invalid character before content-length header value", + "invalid character in content-length header value", + "invalid character after content-length header value", + "content-length parser already done", + "bad content-length parser state", + "overflow in content-length header value", }; fhp_err_t diff --git a/include/fhp/fhp.h b/include/fhp/fhp.h index 46efb44..1e32a0d 100644 --- a/include/fhp/fhp.h +++ b/include/fhp/fhp.h @@ -41,6 +41,12 @@ typedef enum { FHP_ERR_TE_PARSER_DONE, FHP_ERR_NULL_TE_BUF, FHP_ERR_SMALL_TE_BUF, + FHP_ERR_INVALID_CHAR_BEFORE_CL, + FHP_ERR_INVALID_CHAR_IN_CL, + FHP_ERR_INVALID_CHAR_AFTER_CL, + FHP_ERR_CL_PARSER_DONE, + FHP_ERR_BAD_CL_STATE, + FHP_ERR_CL_OVERFLOW, FHP_ERR_LAST } fhp_err_t; @@ -114,6 +120,25 @@ void fhp_env_init(fhp_env_t * const env); fhp_env_t *fhp_get_default_env(void); // +// content length parser functions +// + +typedef enum { + FHP_CL_STATE_INIT, + FHP_CL_STATE_DATA, + FHP_CL_STATE_TRAILING_SPACES, + FHP_CL_STATE_ERROR, + FHP_CL_STATE_DONE, + FHP_CL_STATE_LAST +} fhp_cl_state_t; + +typedef struct { + fhp_cl_state_t state; + fhp_err_t err; + uint64_t val; +} fhp_cl_parser_t; + +// // transfer encoding parser functions // |