[Openvpn-devel] [M] Change in openvpn[master]: Add helper method to read an integer from a buffer
"plaisthos \(Code Review\) via Openvpn-devel" <[email protected]>
| Newsgroups | net.sourceforge.lists.openvpn-devel |
|---|---|
| Message-ID | <[email protected]> |
plaisthos has uploaded this change for review. ( http://gerrit.openvpn.net/c/openvpn/+/1855?usp=email ) Change subject: Add helper method to read an integer from a buffer ...................................................................... Add helper method to read an integer from a buffer Change-Id: Ifdd2122a3e60cdb11cc9df67570ab5628bfcdeea Signed-off-by: Arne Schwabe <[email protected]> --- M src/openvpn/buffer.c M src/openvpn/buffer.h M tests/unit_tests/openvpn/test_buffer.c 3 files changed, 126 insertions(+), 1 deletion(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/55/1855/1 diff --git a/src/openvpn/buffer.c b/src/openvpn/buffer.c index f14caa2..dee0906 100644 --- a/src/openvpn/buffer.c +++ b/src/openvpn/buffer.c @@ -1352,3 +1352,47 @@ fclose(fp); return ret; } + +bool +buffer_read_int(struct buffer *buf, int *result) +{ + *result = 0; + bool ret = false; + + while (buf_len(buf)) + { + uint8_t c = *BPTR(buf); + if (c >= '0' && c <= '9') + { + *result = *result * 10; + /* lower nibble of ascii digits is their value */ + *result += (c & 0x0f); + buf_advance(buf, 1); + ret = true; + } + else + { + return ret; + } + } + return ret; +} + +char * +extract_field(struct buffer *buf, char sep, struct gc_arena *gc) +{ + const uint8_t *seppos = memchr(BPTR(buf), sep, buf_len(buf)); + if (!seppos) + { + return NULL; + } + size_t field_len = seppos - BPTR(buf); + + char *field = gc_malloc(field_len + 1, false, gc); + + strncpy(field, BSTR(buf), field_len); + field[field_len] = 0; + + buf_advance(buf, (int)field_len + 1); + return field; +} \ No newline at end of file diff --git a/src/openvpn/buffer.h b/src/openvpn/buffer.h index 85277ff..c3202fa 100644 --- a/src/openvpn/buffer.h +++ b/src/openvpn/buffer.h @@ -2240,4 +2240,23 @@ /**@}*/ /* End of Buffer Lists */ +/** + * will read a decimal integer from a buffer until the next non-decimal + * character. If successful the method will return true and the integer + * in \c result. The buffer will be advanced to the next character after + * the integer. This function also ensures to not advance beyond the end + * of the buffer. + */ +bool +buffer_read_int(struct buffer *buf, int *result); + +/** + * Extract a field from buf that end with the \c sep character. The + * returned string is allocated in the gc_arena. If the seperator character + * is not found, the function returns the nullptr. + * + * The buffer is also forward to the point after the seperator character. + */ +char * +extract_field(struct buffer *buf, char sep, struct gc_arena *gc); #endif /* BUFFER_H */ diff --git a/tests/unit_tests/openvpn/test_buffer.c b/tests/unit_tests/openvpn/test_buffer.c index 326de40..3575357 100644 --- a/tests/unit_tests/openvpn/test_buffer.c +++ b/tests/unit_tests/openvpn/test_buffer.c @@ -456,6 +456,66 @@ /* Check that our own method agrees */ assert_true(string_check_buf(&buf2, CC_PRINT | CC_NULL, CC_CRLF)); assert_string_equal(BSTR(&buf2), "CR_RESPONSE,MTIx"); + gc_free(&gc); +} + +static void +test_buffer_read_int(void **state) +{ + struct gc_arena gc = gc_new(); + struct buffer buf = alloc_buf_gc(1000, &gc); + + buf_printf(&buf, "72732,1234"); + + int tmp = -1; + assert_true(buffer_read_int(&buf, &tmp)); + assert_int_equal(tmp, 72732); + assert_int_equal(*BPTR(&buf), ','); + + buf_advance(&buf, 1); + + assert_true(buffer_read_int(&buf, &tmp)); + assert_int_equal(tmp, 1234); + assert_int_equal(buf_len(&buf), 0); + + buf = alloc_buf_gc(1000, &gc); + buf_printf(&buf, "fo42,7777"); + + assert_false(buffer_read_int(&buf, &tmp)); + + /* empty buffer */ + buf = alloc_buf_gc(1000, &gc); + assert_false(buffer_read_int(&buf, &tmp)); + + gc_free(&gc); +} + +static void +test_buffer_extract_field(void **state) +{ + struct gc_arena gc = gc_new(); + struct buffer buf = alloc_buf_gc(1000, &gc); + assert_null(extract_field(&buf, ',', &gc)); + + buf = alloc_buf_gc(5, &gc); + buf_write(&buf, "12345", 5); + const char *ret = extract_field(&buf, '5', &gc); + assert_string_equal(ret, "1234"); + /* nothing left after the 5 */ + assert_int_equal(buf_len(&buf), 0); + + buf = alloc_buf_gc(5, &gc); + buf_write(&buf, "12345", 5); + ret = extract_field(&buf, '4', &gc); + assert_string_equal(ret, "123"); + + /* 5 should be left */ + assert_int_equal(buf_len(&buf), 1); + assert_memory_equal(buf_bptr(&buf), "5", 1); + + buf = alloc_buf_gc(5, &gc); + buf_write(&buf, "12345", 5); + assert_null(extract_field(&buf, '6', &gc)); gc_free(&gc); } @@ -567,7 +627,9 @@ cmocka_unit_test(test_checked_snprintf), cmocka_unit_test(test_buffer_chomp), cmocka_unit_test(test_buffer_null_terminate), - cmocka_unit_test(test_buffer_parse) + cmocka_unit_test(test_buffer_parse), + cmocka_unit_test(test_buffer_read_int), + cmocka_unit_test(test_buffer_extract_field) }; return cmocka_run_group_tests_name("buffer", tests, NULL, NULL); -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1855?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings?usp=email Gerrit-MessageType: newchange Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: Ifdd2122a3e60cdb11cc9df67570ab5628bfcdeea Gerrit-Change-Number: 1855 Gerrit-PatchSet: 1 Gerrit-Owner: plaisthos <[email protected]> Gerrit-CC: openvpn-devel <[email protected]> _______________________________________________ Openvpn-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openvpn-devel