/* ---------------- PARSE REQ METHOD ------------------ */ case HTTPs_CONN_STATE_REQ_PARSE_METHOD: HTTPsReq_MethodParse(p_instance, p_conn, &err); switch (err) { case HTTPs_ERR_NONE: /* If the Method parsing is successful... */ p_conn->State = HTTPs_CONN_STATE_REQ_PARSE_URI; /* ...go to the next step. */ break;
default: /* If the Method parsing has failed... */ HTTPs_ERR_INC(p_ctr_err->Req_ErrInvalidCtr); /* ...generate an error... */ p_conn->ErrCode = err; p_conn->State = HTTPs_CONN_STATE_ERR_INTERNAL; p_conn->SockState = HTTPs_SOCK_STATE_NONE; done = DEF_YES; /* ...and exit the state machine. */ break; } break;
/* ------------------ PARSE REQ URI ------------------- */ case HTTPs_CONN_STATE_REQ_PARSE_URI: is_query_str_found = HTTPsReq_URI_Parse(p_instance, p_conn, &err); switch (err) { case HTTPs_ERR_NONE: /* If the URI parsing is successful... */ if (is_query_str_found == DEF_YES) { /* ...check if query string need to be parse. */ p_conn->State = HTTPs_CONN_STATE_REQ_PARSE_QUERY_STRING; } else { p_conn->State = HTTPs_CONN_STATE_REQ_PARSE_PROTOCOL_VERSION; } break;
case HTTPs_ERR_REQ_MORE_DATA_REQUIRED: /* If more data is required to complete the... */ p_conn->SockState = HTTPs_SOCK_STATE_RX; /* ...URI Parsing, exit the state machine. */ done = DEF_YES; break;
default: /* If the URI parsing has failed... */ HTTPs_ERR_INC(p_ctr_err->Req_ErrInvalidCtr); /* ...generate an error... */ p_conn->SockState = HTTPs_SOCK_STATE_NONE; p_conn->ErrCode = err; p_conn->State = HTTPs_CONN_STATE_ERR_INTERNAL; done = DEF_YES; /* ...and exit the state machine. */ break; } break;
/* --------------- PARSE REQ QUERY STR ---------------- */ case HTTPs_CONN_STATE_REQ_PARSE_QUERY_STRING: HTTPsReq_QueryStrParse(p_instance, p_conn, &err); switch (err) { case HTTPs_ERR_NONE: /* If the Query Str parsing is successful... */ /* ...go to the next step. */ p_conn->State = HTTPs_CONN_STATE_REQ_PARSE_PROTOCOL_VERSION; break;
case HTTPs_ERR_REQ_MORE_DATA_REQUIRED: /* If more data is required to complete the... */ p_conn->SockState = HTTPs_SOCK_STATE_RX; /* ...Query Str Parsing, exit the state machine. */ done = DEF_YES; break;
default: /* If the Query Str parsing has failed... */ HTTPs_ERR_INC(p_ctr_err->Req_ErrInvalidCtr); /* ...generate an error... */ p_conn->SockState = HTTPs_SOCK_STATE_NONE; p_conn->ErrCode = err; p_conn->State = HTTPs_CONN_STATE_ERR_INTERNAL; done = DEF_YES; /* ...and exit the state machine. */ break; } break;
/* -------------- PARSE REQ PROTOCOL VER -------------- */ case HTTPs_CONN_STATE_REQ_PARSE_PROTOCOL_VERSION: HTTPsReq_ProtocolVerParse(p_instance, p_conn, &err); switch (err) { case HTTPs_ERR_NONE: /* If the Protocol Ver parsing is successful... */ /* ...go to the next step. */ p_conn->State = HTTPs_CONN_STATE_REQ_PARSE_HDR; p_conn->SockState = HTTPs_SOCK_STATE_NONE; DEF_BIT_CLR(p_conn->Flags, HTTPs_FLAG_RESP_LOCATION); break;
case HTTPs_ERR_REQ_MORE_DATA_REQUIRED: /* If more data is required to complete the... */ p_conn->SockState = HTTPs_SOCK_STATE_RX; /* ...Protocol Ver parsing, exit the state... */ done = DEF_YES; /* ...machine. */ break;
default: /* If the Protocol Ver parsing has failed... */ HTTPs_ERR_INC(p_ctr_err->Req_ErrInvalidCtr); /* ...generate an error... */ p_conn->SockState = HTTPs_SOCK_STATE_NONE; p_conn->ErrCode = err; p_conn->State = HTTPs_CONN_STATE_ERR_INTERNAL; done = DEF_YES; /* ...and exit the state machine. */ break; } break;
/* ------------------ PARSE REQ HDR ------------------- */ case HTTPs_CONN_STATE_REQ_PARSE_HDR: HTTPsReq_HdrParse(p_instance, p_conn, &err); /* See Note #2. */ switch (err) { case HTTPs_ERR_NONE: /* If the Protocol Ver parsing is successful... */ /* ...go to the next step. */ p_conn->State = HTTPs_CONN_STATE_REQ_LINE_HDR_HOOK; p_conn->SockState = HTTPs_SOCK_STATE_NONE; HTTPs_STATS_INC(p_ctr_stats->Req_StatProcessedCtr); break;
case HTTPs_ERR_REQ_MORE_DATA_REQUIRED: /* If more data is required to complete the... */ p_conn->SockState = HTTPs_SOCK_STATE_RX; /* ...Protocol Ver parsing, exit the state... */ done = DEF_YES; /* ...machine. */ break;
default: /* If the Header parsing has failed... */ HTTPs_ERR_INC(p_ctr_err->Req_ErrInvalidCtr); /* ...generate an error... */ p_conn->ErrCode = err; p_conn->State = HTTPs_CONN_STATE_ERR_INTERNAL; done = DEF_YES; /* ...and exit the state machine. */ break; } break;
/* --------------- CONN REQ EXT PROCESS --------------- */ case HTTPs_CONN_STATE_REQ_LINE_HDR_HOOK: hook_def = HTTPs_HOOK_DEFINED(p_cfg->HooksPtr, OnReqHook); if (hook_def == DEF_YES) { accepted = p_cfg->HooksPtr->OnReqHook(p_instance, p_conn, p_cfg->Hooks_CfgPtr); if (accepted != DEF_YES) { /* If the connection is not authorized ... */ if (p_conn->StatusCode == HTTP_STATUS_OK) { p_conn->StatusCode = HTTP_STATUS_UNAUTHORIZED; } DEF_BIT_SET(p_conn->Flags, HTTPs_FLAG_REQ_FLUSH); p_conn->State = HTTPs_CONN_STATE_REQ_BODY_FLUSH_DATA; } } /* Otherwise, receive the body. */ p_conn->State = HTTPs_CONN_STATE_REQ_BODY_INIT; done = DEF_YES; /* ... exit the state machine. */ break;
static CPU_BOOLEAN HTTPsReq_BodyFormAppParse(HTTPs_INSTANCE *p_instance, HTTPs_CONN *p_conn, HTTPs_ERR *p_err) { ... while (done != DEF_YES) { /* ----------- VALIDATE CUR KEY/VAL PAIRS ------------- */ p_key_next = Str_Char_N(p_key_name, /* Srch beginning of next key/val pairs. */ p_conn->RxBufLenRem, ASCII_CHAR_AMPERSAND);
if (p_key_next == DEF_NULL) { /* If next key/val pairs not found ... */ /* ... determine if all data are received or next ... */ /* ... key/val pairs are missing. */ len_content_rxd = p_conn->ReqContentLenRxd + p_conn->RxBufLenRem;
if (len_content_rxd < p_conn->ReqContentLen) { /* If data are missing ... */ *p_err = HTTPs_ERR_REQ_MORE_DATA_REQUIRED; /* ... receive more data. */ gotoexit;
} else { /* If all data received ... */ len_str = p_conn->RxBufLenRem; /* [1] /* ... last key/val pairs to parse. */ }
/* HTTPsReq_ProtocolVerParse */ staticvoidHTTPsReq_ProtocolVerParse(HTTPs_INSTANCE *p_instance, HTTPs_CONN *p_conn, HTTPs_ERR *p_err) { ... len = p_conn->RxBufLenRem; ... /* Move the pointer to the next meaningful char. */ p_protocol_ver_start = HTTP_StrGraphSrchFirst(p_conn->RxBufPtr, len); /* [1] p_protocol_ver_start advances to the first character between 0x21 - 0x7e */ if (p_protocol_ver_start == DEF_NULL) { *p_err = HTTPs_ERR_REQ_FORMAT_INVALID; return; } /* Find the end of the request line. */ p_protocol_ver_end = Str_Str_N(p_protocol_ver_start, STR_CR_LF, len); /* [2] this will search outside of the buffer since len does not account for the previously skipped characters in [1] */ if (p_protocol_ver_end == DEF_NULL) { /* If not found, check to get more data. */ if (p_conn->RxBufPtr != p_conn->BufPtr) { *p_err = HTTPs_ERR_REQ_MORE_DATA_REQUIRED; } else { *p_err = HTTPs_ERR_REQ_FORMAT_INVALID; } return; } ... /* Update the RxBuf ptr. */ p_conn->RxBufLenRem -= (p_protocol_ver_end - p_conn->RxBufPtr) + 2; /* [3] Since p_protocol_ver_end can be outside of the original buffer, this could lead to an integer underflow */ p_conn->RxBufPtr = p_protocol_ver_end + 2; ... }
CPU_BOOLEAN HTTPsSock_ConnDataRx(HTTPs_INSTANCE *p_instance, HTTPs_CONN *p_conn) { ... if ((p_conn->RxBufLenRem > 0) && (p_conn->RxBufPtr != p_conn->BufPtr)) { /* If data is still present in the rx buf. */ /* Move rem data to the beginning of the rx buf. */ Mem_Copy(p_conn->BufPtr, p_conn->RxBufPtr, p_conn->RxBufLenRem); //[1] the length used here is very large because of the underflow } p_buf = p_conn->BufPtr + p_conn->RxBufLenRem; //[2] p_buf now points very far outside of the original buffer buf_len = p_conn->BufLen - p_conn->RxBufLenRem; ... rx_len = (CPU_INT16U)NetSock_RxDataFrom( p_conn->SockID, (void *)p_buf, buf_len, NET_SOCK_FLAG_NO_BLOCK, &p_conn->ClientAddr, &addr_len_client, DEF_NULL, DEF_NULL, DEF_NULL, &err); ... }