plaisthos has uploaded a new patch set (#4). ( 
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, 147 insertions(+), 1 deletion(-)


  git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/55/1855/4

diff --git a/src/openvpn/buffer.c b/src/openvpn/buffer.c
index 046e231..d678f55 100644
--- a/src/openvpn/buffer.c
+++ b/src/openvpn/buffer.c
@@ -1384,3 +1384,53 @@
     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;
+            if (*result < 0)
+            {
+                /* integer overflow */
+                *result = 0;
+                return false;
+            }
+        }
+        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 bc5cffb..871332d 100644
--- a/src/openvpn/buffer.h
+++ b/src/openvpn/buffer.h
@@ -2243,4 +2243,26 @@
 /**@}*/
 /* 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.
+ *
+ * If the result is larger than INT_MAX or the integer cannot be parsed the
+ * function returns false
+ */
+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 ce38bbe..190807a 100644
--- a/tests/unit_tests/openvpn/test_buffer.c
+++ b/tests/unit_tests/openvpn/test_buffer.c
@@ -456,6 +456,78 @@
     /* 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));
+
+    /* integer overflow */
+    uint64_t int_max_plus_one = INT_MAX + 1ull;
+    buf = alloc_buf_gc(1000, &gc);
+    buf_printf(&buf, "%" PRIu64, int_max_plus_one);
+    assert_false(buffer_read_int(&buf, &tmp));
+
+    /* INT MAX  */
+    buf = alloc_buf_gc(1000, &gc);
+    buf_printf(&buf, "%d", INT_MAX);
+    assert_true(buffer_read_int(&buf, &tmp));
+    assert_int_equal(tmp, INT_MAX);
+
+    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 +639,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: newpatchset
Gerrit-Project: openvpn
Gerrit-Branch: master
Gerrit-Change-Id: Ifdd2122a3e60cdb11cc9df67570ab5628bfcdeea
Gerrit-Change-Number: 1855
Gerrit-PatchSet: 4
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