From 568acb832aaaeeb05efadb6c56a88daa7580fc58 Mon Sep 17 00:00:00 2001 From: Cameron Ross Date: Tue, 17 Apr 2018 00:17:10 -0300 Subject: [PATCH] make SliceBuilder safer to use. --- source/dyaml/reader.d | 20 ++++++++++---------- source/dyaml/scanner.d | 14 +++++++------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/source/dyaml/reader.d b/source/dyaml/reader.d index e5120e4..2d1f020 100644 --- a/source/dyaml/reader.d +++ b/source/dyaml/reader.d @@ -531,15 +531,17 @@ public: /// end of the slice being built, the slice is extended (trivial operation). /// /// See_Also: begin - void write(char[] str) @trusted pure nothrow @nogc + void write(char[] str) @safe pure nothrow @nogc { assert(inProgress, "write called without begin"); assert(end_ <= reader_.bufferOffset_, "AT START: Slice ends after buffer position"); + // Nothing? Already done. + if (str.length == 0) { return; } // If str starts at the end of the slice (is a string returned by a Reader // method), just extend the slice to contain str. - if(str.ptr == reader_.buffer_.ptr + end_) + if(&str[0] == &reader_.buffer_[end_]) { end_ += str.length; } @@ -547,8 +549,7 @@ public: // by a Reader method and point to buffer. So we need to memmove. else { - core.stdc.string.memmove(reader_.buffer_.ptr + end_, cast(char*)str.ptr, - str.length * char.sizeof); + copy(str, reader_.buffer_[end_..end_ + str.length * char.sizeof]); end_ += str.length; } } @@ -585,7 +586,7 @@ public: /// position = Position to insert the character at in code units, not code points. /// Must be less than slice length(); a previously returned length() /// can be used. - void insert(const dchar c, const size_t position) @system pure nothrow @nogc + void insert(const dchar c, const size_t position) @safe pure nothrow @nogc { assert(inProgress, "insert called without begin"); assert(start_ + position <= end_, "Trying to insert after the end of the slice"); @@ -600,9 +601,8 @@ public: if(movedLength > 0) { - core.stdc.string.memmove(reader_.buffer_.ptr + point + bytes, - reader_.buffer_.ptr + point, - movedLength * char.sizeof); + copy(reader_.buffer_[point..point + movedLength * char.sizeof], + reader_.buffer_[point + bytes..point + bytes + movedLength * char.sizeof]); } reader_.buffer_[point .. point + bytes] = encodeBuf[0 .. bytes]; end_ += bytes; @@ -635,9 +635,9 @@ public: /// ended either by commit()-ing or reverting through the destructor. /// /// Saves the current state of a slice. - this(ref SliceBuilder builder) @system pure nothrow @nogc + this(SliceBuilder* builder) @safe pure nothrow @nogc { - builder_ = &builder; + builder_ = builder; stackLevel_ = builder_.endStackUsed_; builder_.push(); } diff --git a/source/dyaml/scanner.d b/source/dyaml/scanner.d index b68ea82..df0b2f9 100644 --- a/source/dyaml/scanner.d +++ b/source/dyaml/scanner.d @@ -1210,7 +1210,7 @@ final class Scanner /// Scan a block scalar token with specified style. /// /// In case of an error, error_ is set. Use throwIfError() to handle this. - Token scanBlockScalar(const ScalarStyle style) @trusted + Token scanBlockScalar(const ScalarStyle style) @safe { const startMark = reader_.mark; @@ -1233,7 +1233,7 @@ final class Scanner alias Transaction = SliceBuilder.Transaction; // Used to strip the last line breaks written to the slice at the end of the // scalar, which may be needed based on chomping. - Transaction breaksTransaction = Transaction(reader_.sliceBuilder); + Transaction breaksTransaction = Transaction(&reader_.sliceBuilder); // Read the first indentation/line breaks before the scalar. size_t startLen = reader_.sliceBuilder.length; if(increment == int.min) @@ -1263,7 +1263,7 @@ final class Scanner // This transaction serves to rollback data read in the // scanBlockScalarBreaksToSlice() call. - breaksTransaction = Transaction(reader_.sliceBuilder); + breaksTransaction = Transaction(&reader_.sliceBuilder); startLen = reader_.sliceBuilder.length; // The line breaks should actually be written _after_ the if() block // below. We work around that by inserting @@ -1712,7 +1712,7 @@ final class Scanner /// Scan plain scalar token (no block, no quotes). /// /// In case of an error, error_ is set. Use throwIfError() to handle this. - Token scanPlain() @trusted + Token scanPlain() @safe { // We keep track of the allowSimpleKey_ flag here. // Indentation rules are loosed for the flow context @@ -1788,7 +1788,7 @@ final class Scanner endMark = reader_.mark; spacesTransaction.commit(); - spacesTransaction = Transaction(reader_.sliceBuilder); + spacesTransaction = Transaction(&reader_.sliceBuilder); const startLength = reader_.sliceBuilder.length; scanPlainSpacesToSlice(startMark); @@ -1809,7 +1809,7 @@ final class Scanner /// /// Assumes that the caller is building a slice in Reader, and puts the spaces /// into that slice. - void scanPlainSpacesToSlice(const Mark startMark) @system + void scanPlainSpacesToSlice(const Mark startMark) @safe { // The specification is really confusing about tabs in plain scalars. // We just forbid them completely. Do not use tabs in YAML! @@ -1847,7 +1847,7 @@ final class Scanner bool extraBreaks = false; alias Transaction = SliceBuilder.Transaction; - auto transaction = Transaction(reader_.sliceBuilder); + auto transaction = Transaction(&reader_.sliceBuilder); if(lineBreak != '\n') { reader_.sliceBuilder.write(lineBreak); } while(search.canFind(reader_.peek())) {