in source/hpack.c [955:1049]
int aws_hpack_decode_string(
struct aws_hpack_context *context,
struct aws_byte_cursor *to_decode,
struct aws_byte_buf *output,
bool *complete) {
AWS_PRECONDITION(context);
AWS_PRECONDITION(to_decode);
AWS_PRECONDITION(output);
AWS_PRECONDITION(complete);
struct hpack_progress_string *progress = &context->progress_string;
while (to_decode->len) {
switch (progress->state) {
case HPACK_STRING_STATE_INIT: {
/* Do init stuff */
progress->state = HPACK_STRING_STATE_LENGTH;
progress->use_huffman = *to_decode->ptr >> 7;
aws_huffman_decoder_reset(&context->decoder);
/* fallthrough, since we didn't consume any data */
}
/* FALLTHRU */
case HPACK_STRING_STATE_LENGTH: {
bool length_complete = false;
if (aws_hpack_decode_integer(context, to_decode, 7, &progress->length, &length_complete)) {
return AWS_OP_ERR;
}
if (!length_complete) {
goto handle_ongoing;
}
if (progress->length == 0) {
goto handle_complete;
}
if (progress->length > SIZE_MAX) {
return aws_raise_error(AWS_ERROR_OVERFLOW_DETECTED);
}
progress->state = HPACK_STRING_STATE_VALUE;
} break;
case HPACK_STRING_STATE_VALUE: {
/* Take either as much data as we need, or as much as we can */
size_t to_process = aws_min_size((size_t)progress->length, to_decode->len);
progress->length -= to_process;
struct aws_byte_cursor chunk = aws_byte_cursor_advance(to_decode, to_process);
if (progress->use_huffman) {
if (aws_huffman_decode(&context->decoder, &chunk, output)) {
HPACK_LOGF(ERROR, context, "Error from Huffman decoder: %s", aws_error_name(aws_last_error()));
return AWS_OP_ERR;
}
/* Decoder should consume all bytes we feed it.
* EOS (end-of-string) symbol could stop it early, but HPACK says to treat EOS as error. */
if (chunk.len != 0) {
HPACK_LOG(ERROR, context, "Huffman encoded end-of-string symbol is illegal");
return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
}
} else {
if (aws_byte_buf_append_dynamic(output, &chunk)) {
return AWS_OP_ERR;
}
}
/* If whole length consumed, we're done */
if (progress->length == 0) {
/* #TODO Validate any padding bits left over in final byte of string.
* "A padding not corresponding to the most significant bits of the
* code for the EOS symbol MUST be treated as a decoding error" */
/* #TODO impose limits on string length */
goto handle_complete;
}
} break;
}
}
handle_ongoing:
/* Fell out of to_decode loop, must still be in progress */
AWS_ASSERT(to_decode->len == 0);
*complete = false;
return AWS_OP_SUCCESS;
handle_complete:
AWS_ASSERT(context->progress_string.length == 0);
AWS_ZERO_STRUCT(context->progress_string);
*complete = true;
return AWS_OP_SUCCESS;
}