vppinfra: fix longstanding corner case bug in serialize_get() 10/37910/2
authorDave Barach <dave@barachs.net>
Thu, 12 Jan 2023 21:07:26 +0000 (16:07 -0500)
committerFlorin Coras <florin.coras@gmail.com>
Thu, 12 Jan 2023 23:03:22 +0000 (23:03 +0000)
serialize_get() -> serialize_write_not_inline(...) was losing track of
the current buffer index when it managed to empty the overflow vector
but had to turn around and use it again.

Test-case added to test_serialize.c.

This issue dates from 2010.

Type: fix

Signed-off-by: Dave Barach <dave@barachs.net>
Change-Id: I024a03f7a50fd6df543ddbc7c45d85def4f1981d

src/vppinfra/serialize.c
src/vppinfra/test_serialize.c

index f5c0064..ceda617 100644 (file)
@@ -741,6 +741,7 @@ serialize_write_not_inline (serialize_main_header_t * m,
   if (n_left_o > 0 || n_left_b < n_bytes_to_write)
     {
       u8 *r;
+      s->current_buffer_index = cur_bi;
       vec_add2 (s->overflow_buffer, r, n_bytes_to_write);
       return r;
     }
index 5c931b7..0dcff03 100644 (file)
@@ -136,6 +136,46 @@ typedef struct
   serialize_main_t unserialize_main;
 } test_serialize_main_t;
 
+u8 *test_pattern;
+
+int
+vl (void *p)
+{
+  return vec_len (p);
+}
+
+void
+test_serialize_not_inline_double_vector_expand (void)
+{
+  serialize_main_t _m, *m = &_m;
+  u8 *serialized = 0;
+  u64 *magic;
+  void *p;
+  int i;
+
+  vec_validate (test_pattern, 1023);
+
+  for (i = 0; i < vec_len (test_pattern); i++)
+    test_pattern[i] = i & 0xff;
+
+  serialize_open_vector (m, serialized);
+  p = serialize_get (m, 61);
+  clib_memcpy_fast (p, test_pattern, 61);
+  serialize_integer (m, 0xDEADBEEFFEEDFACEULL, 8);
+  p = serialize_get (m, vec_len (test_pattern) - 62);
+  clib_memcpy_fast (p, test_pattern + 61, vec_len (test_pattern) - 62);
+  serialized = serialize_close_vector (m);
+
+  magic = (u64 *) (serialized + 61);
+
+  if (*magic != clib_net_to_host_u64 (0xDEADBEEFFEEDFACEULL))
+    {
+      fformat (stderr, "BUG!\n");
+      exit (1);
+    }
+  return;
+}
+
 int
 test_serialize_main (unformat_input_t * input)
 {
@@ -168,6 +208,12 @@ test_serialize_main (unformat_input_t * input)
        ;
       else if (unformat (input, "verbose %=", &tm->verbose, 1))
        ;
+      else if (unformat (input, "double-expand"))
+       {
+         test_serialize_not_inline_double_vector_expand ();
+         clib_warning ("serialize_not_inline double vector expand OK");
+         exit (0);
+       }
       else
        {
          error = clib_error_create ("unknown input `%U'\n",