[M] Change in openvpn[master]: Add helper method to read an integer from a buffer

"plaisthos \(Code Review\) via Openvpn-devel" <[email protected]>
Newsgroups gmane.network.openvpn.devel
Message-ID <2de0fe30f0d5aaf190dfe4eccc15165113393384-EmailReplacePatchSet-HTML@gerrit.openvpn.net>
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
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.