[PATCH] D60505: YAMLIO: Fix serialization of strings with embedded nuls

Pavel Labath via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 10 04:55:33 PDT 2019


labath created this revision.
labath added reviewers: sammccall, jhenderson.
Herald added a subscriber: kristina.
Herald added a project: LLVM.

A bug/typo in Output::scalarString caused us to round-trip a StringRef
through a const char *. This meant that any strings with embedded nuls
were unintentionally cut short at the first such character. (It also
could have caused accidental buffer overruns, but it seems that all
StringRefs coming into this functions were formed from null-terminated
strings.)

This patch fixes the bug and adds an appropriate test.


Repository:
  rL LLVM

https://reviews.llvm.org/D60505

Files:
  lib/Support/YAMLTraits.cpp
  unittests/Support/YAMLIOTest.cpp


Index: unittests/Support/YAMLIOTest.cpp
===================================================================
--- unittests/Support/YAMLIOTest.cpp
+++ unittests/Support/YAMLIOTest.cpp
@@ -688,6 +688,7 @@
   std::string stdstr10;
   std::string stdstr11;
   std::string stdstr12;
+  std::string stdstr13;
 };
 
 namespace llvm {
@@ -718,6 +719,7 @@
       io.mapRequired("stdstr10",  st.stdstr10);
       io.mapRequired("stdstr11",  st.stdstr11);
       io.mapRequired("stdstr12",  st.stdstr12);
+      io.mapRequired("stdstr13",  st.stdstr13);
     }
   };
 }
@@ -750,6 +752,7 @@
     map.stdstr10 = "0.2e20";
     map.stdstr11 = "0x30";
     map.stdstr12 = "- match";
+    map.stdstr13.assign("\0a\0b\0", 5);
 
     llvm::raw_string_ostream ostr(intermediate);
     Output yout(ostr);
@@ -775,6 +778,7 @@
   EXPECT_NE(std::string::npos, flowOut.find("'@hhh'"));
   EXPECT_NE(std::string::npos, flowOut.find("''\n"));
   EXPECT_NE(std::string::npos, flowOut.find("'0000000004000000'\n"));
+  EXPECT_NE(std::string::npos, flowOut.find("\"\\0a\\0b\\0\""));
 
   {
     Input yin(intermediate);
@@ -794,6 +798,7 @@
     EXPECT_TRUE(map.stdstr4 == "@hhh");
     EXPECT_TRUE(map.stdstr5 == "");
     EXPECT_TRUE(map.stdstr6 == "0000000004000000");
+    EXPECT_EQ(std::string("\0a\0b\0", 5), map.stdstr13);
   }
 }
 
Index: lib/Support/YAMLTraits.cpp
===================================================================
--- lib/Support/YAMLTraits.cpp
+++ lib/Support/YAMLTraits.cpp
@@ -660,11 +660,6 @@
     return;
   }
 
-  unsigned i = 0;
-  unsigned j = 0;
-  unsigned End = S.size();
-  const char *Base = S.data();
-
   const char *const Quote = MustQuote == QuotingType::Single ? "'" : "\"";
   output(Quote); // Starting quote.
 
@@ -672,11 +667,16 @@
   // present, and will be escaped using a variety of unicode-scalar and special short-form
   // escapes. This is handled in yaml::escape.
   if (MustQuote == QuotingType::Double) {
-    output(yaml::escape(Base, /* EscapePrintable= */ false));
+    output(yaml::escape(S, /* EscapePrintable= */ false));
     outputUpToEndOfLine(Quote);
     return;
   }
 
+  unsigned i = 0;
+  unsigned j = 0;
+  unsigned End = S.size();
+  const char *Base = S.data();
+
   // When using single-quoted strings, any single quote ' must be doubled to be escaped.
   while (j < End) {
     if (S[j] == '\'') {                    // Escape quotes.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D60505.194491.patch
Type: text/x-patch
Size: 2383 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190410/d5e8792e/attachment.bin>


More information about the llvm-commits mailing list