From e816026faa1ae11f0e9d26d27f420a304d4ad210 Mon Sep 17 00:00:00 2001 From: Jan Breuer <jan.breuer@jaybee.cz> Date: 周五, 16 10月 2015 06:16:45 +0800 Subject: [PATCH] Resolve #59: input buffer overrun handling --- libscpi/inc/scpi/error.h | 2 libscpi/src/ieee488.c | 6 ++- libscpi/src/parser.c | 43 ++++++++++++++------- libscpi/inc/scpi/parser.h | 4 +- libscpi/test/test_parser.c | 21 ++++++---- 5 files changed, 48 insertions(+), 28 deletions(-) diff --git a/libscpi/inc/scpi/error.h b/libscpi/inc/scpi/error.h index 81f74fd..539ebae 100644 --- a/libscpi/inc/scpi/error.h +++ b/libscpi/inc/scpi/error.h @@ -168,7 +168,7 @@ XE(SCPI_ERROR_COMMUNICATION_ERROR, -360, "Communication error") \ XE(SCPI_ERROR_PARITY_ERROR_IN_CMD_MSG, -361, "Parity error in program message") \ XE(SCPI_ERROR_FRAMING_ERROR_IN_CMD_MSG, -362, "Framing error in program message") \ - XE(SCPI_ERROR_INPUT_BUFFER_OVERRUN, -363, "Input buffer overrun") \ + X(SCPI_ERROR_INPUT_BUFFER_OVERRUN, -363, "Input buffer overrun") \ XE(SCPI_ERROR_TIME_OUT, -365, "Time out error") \ XE(SCPI_ERROR_QUERY_ERROR, -400, "Query error") \ XE(SCPI_ERROR_QUERY_INTERRUPTED, -410, "Query INTERRUPTED") \ diff --git a/libscpi/inc/scpi/parser.h b/libscpi/inc/scpi/parser.h index 539bf1b..1e26a6b 100644 --- a/libscpi/inc/scpi/parser.h +++ b/libscpi/inc/scpi/parser.h @@ -45,8 +45,8 @@ #endif void SCPI_Init(scpi_t * context); - int SCPI_Input(scpi_t * context, const char * data, int len); - int SCPI_Parse(scpi_t * context, char * data, int len); + scpi_bool_t SCPI_Input(scpi_t * context, const char * data, int len); + scpi_bool_t SCPI_Parse(scpi_t * context, char * data, int len); size_t SCPI_ResultCharacters(scpi_t * context, const char * data, size_t len); #define SCPI_ResultMnemonic(context, data) SCPI_ResultCharacters((context), (data), strlen(data)) diff --git a/libscpi/src/ieee488.c b/libscpi/src/ieee488.c index cd527e3..55a9e22 100644 --- a/libscpi/src/ieee488.c +++ b/libscpi/src/ieee488.c @@ -213,8 +213,9 @@ int32_t new_ESE; if (SCPI_ParamInt32(context, &new_ESE, TRUE)) { SCPI_RegSet(context, SCPI_REG_ESE, (scpi_reg_val_t) new_ESE); + return SCPI_RES_OK; } - return SCPI_RES_OK; + return SCPI_RES_ERR; } /** @@ -303,8 +304,9 @@ int32_t new_SRE; if (SCPI_ParamInt32(context, &new_SRE, TRUE)) { SCPI_RegSet(context, SCPI_REG_SRE, (scpi_reg_val_t) new_SRE); + return SCPI_RES_OK; } - return SCPI_RES_OK; + return SCPI_RES_ERR; } /** diff --git a/libscpi/src/parser.c b/libscpi/src/parser.c index acb53a8..b040c5e 100644 --- a/libscpi/src/parser.c +++ b/libscpi/src/parser.c @@ -118,9 +118,10 @@ * Process command * @param context */ -static void processCommand(scpi_t * context) { +static scpi_bool_t processCommand(scpi_t * context) { const scpi_command_t * cmd = context->param_list.cmd; lex_state_t * state = &context->param_list.lex_state; + scpi_bool_t result = TRUE; /* conditionaly write ; */ writeSemicolon(context); @@ -131,15 +132,25 @@ /* if callback exists - call command callback */ if (cmd->callback != NULL) { - if ((cmd->callback(context) != SCPI_RES_OK) && !context->cmd_error) { - SCPI_ErrorPush(context, SCPI_ERROR_EXECUTION_ERROR); + if ((cmd->callback(context) != SCPI_RES_OK)) { + if (!context->cmd_error) { + SCPI_ErrorPush(context, SCPI_ERROR_EXECUTION_ERROR); + } + result = FALSE; + } else { + if (context->cmd_error) { + result = FALSE; + } } } /* set error if command callback did not read all parameters */ if (state->pos < (state->buffer + state->len) && !context->cmd_error) { SCPI_ErrorPush(context, SCPI_ERROR_PARAMETER_NOT_ALLOWED); + result = FALSE; } + + return result; } /** @@ -166,28 +177,27 @@ * @param context * @param data - complete command line * @param len - command line length - * @return 1 if the last evaluated command was found + * @return FALSE if there was some error during evaluation of commands */ -int SCPI_Parse(scpi_t * context, char * data, int len) { - int result = 0; +scpi_bool_t SCPI_Parse(scpi_t * context, char * data, int len) { + scpi_bool_t result = TRUE; scpi_parser_state_t * state; int r; scpi_token_t cmd_prev = {SCPI_TOKEN_UNKNOWN, NULL, 0}; if (context == NULL) { - return -1; + return FALSE; } state = &context->parser_state; context->output_count = 0; while (1) { - result = 0; - r = scpiParser_detectProgramMessageUnit(state, data, len); if (state->programHeader.type == SCPI_TOKEN_INVALID) { SCPI_ErrorPush(context, SCPI_ERROR_INVALID_CHARACTER); + result = FALSE; } else if (state->programHeader.len > 0) { composeCompoundCommand(&cmd_prev, &state->programHeader); @@ -201,12 +211,11 @@ context->param_list.cmd_raw.position = 0; context->param_list.cmd_raw.length = state->programHeader.len; - processCommand(context); - - result = 1; + result &= processCommand(context); cmd_prev = state->programHeader; } else { SCPI_ErrorPush(context, SCPI_ERROR_UNDEFINED_HEADER); + result = FALSE; } } @@ -260,8 +269,8 @@ * @param len - length of data * @return */ -int SCPI_Input(scpi_t * context, const char * data, int len) { - int result = 0; +scpi_bool_t SCPI_Input(scpi_t * context, const char * data, int len) { + scpi_bool_t result = TRUE; size_t totcmdlen = 0; int cmdlen = 0; @@ -274,7 +283,11 @@ buffer_free = context->buffer.length - context->buffer.position; if (len > (buffer_free - 1)) { - return -1; + /* Input buffer overrun - invalidate buffer */ + context->buffer.position = 0; + context->buffer.data[context->buffer.position] = 0; + SCPI_ErrorPush(context, SCPI_ERROR_INPUT_BUFFER_OVERRUN); + return FALSE; } memcpy(&context->buffer.data[context->buffer.position], data, len); context->buffer.position += len; diff --git a/libscpi/test/test_parser.c b/libscpi/test/test_parser.c index bf79478..8114266 100644 --- a/libscpi/test/test_parser.c +++ b/libscpi/test/test_parser.c @@ -241,19 +241,24 @@ output_buffer_clear(); error_buffer_clear(); -#define TEST_ERROR(data, output, err_num) { \ +#define TEST_ERROR(data, output, expected_result, err_num) { \ output_buffer_clear(); \ error_buffer_clear(); \ - SCPI_Input(&scpi_context, data, strlen(data)); \ + scpi_bool_t result = SCPI_Input(&scpi_context, data, strlen(data)); \ CU_ASSERT_STRING_EQUAL(output, output_buffer); \ - CU_ASSERT_EQUAL(err_buffer[0], err_num) \ + CU_ASSERT_EQUAL(err_buffer[0], err_num); \ + CU_ASSERT_EQUAL(result, expected_result); \ } - TEST_ERROR("*IDN?\r\n", "MA,IN,0,VER\r\n", 0); - TEST_ERROR("IDN?\r\n", "", SCPI_ERROR_UNDEFINED_HEADER); - TEST_ERROR("*ESE\r\n", "", SCPI_ERROR_MISSING_PARAMETER); - TEST_ERROR("*IDN? 12\r\n", "MA,IN,0,VER\r\n", SCPI_ERROR_PARAMETER_NOT_ALLOWED); - TEST_ERROR("TEXT? \"PARAM1\", \"PARAM2\"\r\n", "\"PARAM2\"\r\n", 0); + TEST_ERROR("*IDN?\r\n", "MA,IN,0,VER\r\n", TRUE, 0); + TEST_ERROR("IDN?\r\n", "", FALSE, SCPI_ERROR_UNDEFINED_HEADER); + TEST_ERROR("*ESE\r\n", "", FALSE, SCPI_ERROR_MISSING_PARAMETER); + TEST_ERROR("*IDN? 12\r\n", "MA,IN,0,VER\r\n", FALSE, SCPI_ERROR_PARAMETER_NOT_ALLOWED); + TEST_ERROR("TEXT? \"PARAM1\", \"PARAM2\"\r\n", "\"PARAM2\"\r\n", TRUE, 0); + TEST_ERROR("ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJ" + "ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJ" + "ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJ", + "", FALSE, SCPI_ERROR_INPUT_BUFFER_OVERRUN); // TODO: SCPI_ERROR_INVALID_SEPARATOR // TODO: SCPI_ERROR_INVALID_SUFFIX -- Gitblit v1.9.1