yaml-cpp icon indicating copy to clipboard operation
yaml-cpp copied to clipboard

Single carriage return line endings cause an exception

Open jwelsch opened this issue 4 years ago • 1 comments
trafficstars

Description

YAML files that use single carriage returns for line endings can cause an exception to be thrown. There are at least two scenarios that can cause an exception. The first is when the carriage return is on the first line. A YAML::ParserException is thrown when calling YAML::LoadFile(). The second is when the carriage return is on a nested node. It can throw a YAML::TypedBadConversion when calling Node::as<T>().

According to the YAML specs, a single carriage return is a valid line break. https://yaml.org/spec/1.2/spec.html#id2774608

Reproduction Steps

To throw a YAML::ParserException, execute the following code with the attached file:

auto root = YAML::LoadFile("first-line-cr.yaml"); // Exception thrown here

To throw a YAML::TypedBadConversion, execute the following code with the attached file:

auto root = YAML::LoadFile("nested-node-cr.yaml");
auto foo = root["foo"];
auto bar = foo["bar"];
auto hello = bar["hello"];
auto a = hello.as<std::string>(); // Exception thrown here

Files containing example YAML can be found in this ZIP: examples.zip

jwelsch avatar Apr 20 '21 16:04 jwelsch

This turned out to be pretty ugly.

I think the following diff patches it.

diff --git a/src/exp.h b/src/exp.h
index 301449e..a0d6d76 100644
--- a/src/exp.h
+++ b/src/exp.h
@@ -37,7 +37,7 @@ inline const RegEx& Blank() {
   return e;
 }
 inline const RegEx& Break() {
-  static const RegEx e = RegEx('\n') | RegEx("\r\n");
+  static const RegEx e = RegEx('\n') | RegEx("\r\n") | RegEx('\r');
   return e;
 }
 inline const RegEx& BlankOrBreak() {
diff --git a/src/stream.cpp b/src/stream.cpp
index b1aa092..ab83293 100644
--- a/src/stream.cpp
+++ b/src/stream.cpp
@@ -262,7 +262,7 @@ char Stream::get() {
   AdvanceCurrent();
   m_mark.column++;
 
-  if (ch == '\n') {
+  if (ch == '\n' || (ch == '\r' && peek() != '\n')) {
     m_mark.column = 0;
     m_mark.line++;
   }

Akaame avatar Aug 03 '21 21:08 Akaame