aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/plugins/unittest/CMakeLists.txt1
-rw-r--r--src/plugins/unittest/test_buffer.c91
-rw-r--r--src/vlib/buffer_funcs.h12
3 files changed, 101 insertions, 3 deletions
diff --git a/src/plugins/unittest/CMakeLists.txt b/src/plugins/unittest/CMakeLists.txt
index 5b7e1f7655e..3e0e550b609 100644
--- a/src/plugins/unittest/CMakeLists.txt
+++ b/src/plugins/unittest/CMakeLists.txt
@@ -36,4 +36,5 @@ add_vpp_plugin(unittest
svm_fifo_test.c
unittest.c
util_test.c
+ test_buffer.c
)
diff --git a/src/plugins/unittest/test_buffer.c b/src/plugins/unittest/test_buffer.c
new file mode 100644
index 00000000000..e5a5643099c
--- /dev/null
+++ b/src/plugins/unittest/test_buffer.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vlib/vlib.h>
+#include <vlib/buffer_funcs.h>
+
+#define TEST_I(_cond, _comment, _args...) \
+({ \
+ int _evald = (_cond); \
+ if (!(_evald)) { \
+ fformat(stderr, "FAIL:%d: " _comment "\n", \
+ __LINE__, ##_args); \
+ } else { \
+ fformat(stderr, "PASS:%d: " _comment "\n", \
+ __LINE__, ##_args); \
+ } \
+ _evald; \
+})
+
+#define TEST(_cond, _comment, _args...) \
+{ \
+ if (!TEST_I(_cond, _comment, ##_args)) { \
+ return 1; \
+ } \
+}
+
+/* test function for a specific case where current_data is negative, verify
+ * that there is no crash */
+static int
+linearize_negative_current_data (vlib_main_t * vm)
+{
+ u32 bi[32];
+ TEST (ARRAY_LEN (bi) == vlib_buffer_alloc (vm, bi, ARRAY_LEN (bi)),
+ "buff alloc");
+ u32 data_size = vlib_buffer_get_default_data_size (vm);
+ u32 i;
+ for (i = 0; i < ARRAY_LEN (bi) - 1; ++i)
+ {
+ vlib_buffer_t *b = vlib_get_buffer (vm, bi[i]);
+ b->next_buffer = bi[i + 1];
+ b->flags |= VLIB_BUFFER_NEXT_PRESENT;
+ b->current_data = -14;
+ b->current_length = 14 + data_size;
+ }
+
+ vlib_buffer_chain_linearize (vm, vlib_get_buffer (vm, bi[0]));
+
+ return 0;
+}
+
+static clib_error_t *
+test_linearize_fn (vlib_main_t * vm, unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+
+ if (linearize_negative_current_data (vm))
+ {
+ return clib_error_return (0, "linearize_negative_current_data failed");
+ }
+
+ return (NULL);
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (test_linearize_command, static) =
+{
+ .path = "test chained-buffer-linearization",
+ .short_help = "test chained-buffer-linearization",
+ .function = test_linearize_fn,
+};
+/* *INDENT-ON* */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/src/vlib/buffer_funcs.h b/src/vlib/buffer_funcs.h
index 521a036812c..8091d83729c 100644
--- a/src/vlib/buffer_funcs.h
+++ b/src/vlib/buffer_funcs.h
@@ -1416,13 +1416,19 @@ vlib_buffer_chain_linearize (vlib_main_t * vm, vlib_buffer_t * b)
if (dst_left == 0)
{
- if (db != first)
- db->current_data = 0;
db->current_length = dp - (u8 *) vlib_buffer_get_current (db);
ASSERT (db->flags & VLIB_BUFFER_NEXT_PRESENT);
db = vlib_get_buffer (vm, db->next_buffer);
dst_left = data_size;
- dp = db->data;
+ if (db->current_data > 0)
+ {
+ db->current_data = 0;
+ }
+ else
+ {
+ dst_left += -db->current_data;
+ }
+ dp = vlib_buffer_get_current (db);
}
while (src_left == 0)