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

Reply via email to