[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.