From 9522a0b7c16414fce2103cf58bfdd63aaf0cb01b Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 3 Nov 2022 14:58:32 -0400 Subject: DRTVWR-575: Fix llcommon assumptions that size_t fits in 4 bytes. It's a little distressing how often we have historically coded S32 or U32 to pass a length or index. There are more such assumptions in other viewer subdirectories, but this is a start. --- indra/llcommon/llstreamtools.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'indra/llcommon/llstreamtools.cpp') diff --git a/indra/llcommon/llstreamtools.cpp b/indra/llcommon/llstreamtools.cpp index d7a6f47932..1eccfda755 100644 --- a/indra/llcommon/llstreamtools.cpp +++ b/indra/llcommon/llstreamtools.cpp @@ -118,7 +118,7 @@ bool skip_to_next_word(std::istream& input_stream) bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream) { - int key_length = strlen(keyword); /*Flawfinder: ignore*/ + auto key_length = strlen(keyword); /*Flawfinder: ignore*/ if (0 == key_length) { return false; @@ -315,7 +315,7 @@ bool unget_line(const std::string& line, std::istream& input_stream) // returns true if removed last char bool remove_last_char(char c, std::string& line) { - int line_size = line.size(); + auto line_size = line.size(); if (line_size > 1 && c == line[line_size - 1]) { @@ -330,8 +330,8 @@ bool remove_last_char(char c, std::string& line) // "\\n" ---> '\n' (backslash n becomes carriage return) void unescape_string(std::string& line) { - int line_size = line.size(); - int index = 0; + auto line_size = line.size(); + size_t index = 0; while (index < line_size - 1) { if ('\\' == line[index]) @@ -356,8 +356,8 @@ void unescape_string(std::string& line) // '\n' ---> "\\n" (carriage return becomes backslash n) void escape_string(std::string& line) { - int line_size = line.size(); - int index = 0; + auto line_size = line.size(); + size_t index = 0; while (index < line_size) { if ('\\' == line[index]) @@ -379,8 +379,8 @@ void escape_string(std::string& line) // removes '\n' characters void replace_newlines_with_whitespace(std::string& line) { - int line_size = line.size(); - int index = 0; + auto line_size = line.size(); + size_t index = 0; while (index < line_size) { if ('\n' == line[index]) @@ -394,8 +394,8 @@ void replace_newlines_with_whitespace(std::string& line) // erases any double-quote characters in 'line' void remove_double_quotes(std::string& line) { - int index = 0; - int line_size = line.size(); + size_t index = 0; + auto line_size = line.size(); while (index < line_size) { if ('"' == line[index]) @@ -424,8 +424,8 @@ void get_keyword_and_value(std::string& keyword, const std::string& line) { // skip initial whitespace - int line_size = line.size(); - int line_index = 0; + auto line_size = line.size(); + size_t line_index = 0; char c; while (line_index < line_size) { -- cgit v1.2.3 From abe62c23d74d5319691a49881719b03cc9b5b090 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 22 Nov 2022 16:21:44 -0500 Subject: SL-18330: Make LLSDSerialize::deserialize() default to notation. LLSDSerialize::serialize() emits a header string, e.g. "" for notation format. Until now, LLSDSerialize::deserialize() has required that header to properly decode the input stream. But none of LLSDBinaryFormatter, LLSDXMLFormatter or LLSDNotationFormatter emit that header themselves. Nor do any of the Python llsd.format_binary(), format_xml() or format_notation() functions. Until now, you could not use LLSD::deserialize() to parse an arbitrary-format LLSD stream serialized by anything but LLSDSerialize::serialize(). Change LLSDSerialize::deserialize() so that if no header is recognized, instead of failing, it attempts to parse as notation. Add tests to exercise this case. The tricky part about this processing is that deserialize() necessarily reads some number of bytes from the input stream first, to try to recognize the header. If it fails to do so, it must prepend the bytes it has already read to the rest of the input stream since they're probably the beginning of the serialized data. To support this use case, introduce cat_streambuf, a std::streambuf subclass that (virtually) concatenates other std::streambuf instances. When read by a std::istream, the sequence of underlying std::streambufs appears to the consumer as a single continuous stream. --- indra/llcommon/llstreamtools.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'indra/llcommon/llstreamtools.cpp') diff --git a/indra/llcommon/llstreamtools.cpp b/indra/llcommon/llstreamtools.cpp index d7a6f47932..1674f6edc2 100644 --- a/indra/llcommon/llstreamtools.cpp +++ b/indra/llcommon/llstreamtools.cpp @@ -523,3 +523,29 @@ std::istream& operator>>(std::istream& str, const char *tocheck) } return str; } + +int cat_streambuf::underflow() +{ + if (gptr() == egptr()) + { + // here because our buffer is empty + std::streamsize size; + // Until we've run out of mInputs, try reading the first of them + // into mBuffer. If that fetches some characters, break the loop. + while (! mInputs.empty() + && ! (size = mInputs.front()->sgetn(mBuffer.data(), mBuffer.size()))) + { + // We tried to read mInputs.front() but got zero characters. + // Discard the first streambuf and try the next one. + mInputs.pop_front(); + } + // Either we ran out of mInputs or we succeeded in reading some + // characters, that is, size != 0. Tell base class what we have. + setg(mBuffer.data(), mBuffer.data(), mBuffer.data() + size); + } + // If we fell out of the above loop with mBuffer still empty, return + // eof(), otherwise return the next character. + return (gptr() == egptr()) + ? std::char_traits::eof() + : std::char_traits::to_int_type(*gptr()); +} -- cgit v1.2.3 From 9a7e638b67cda4bb1174a4d46fb7769290472ebc Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 6 Dec 2022 15:46:05 -0500 Subject: DRTVWR-575: Defend unescape_string() against empty line. The unsigned index arithmetic was problematic in that case. --- indra/llcommon/llstreamtools.cpp | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) (limited to 'indra/llcommon/llstreamtools.cpp') diff --git a/indra/llcommon/llstreamtools.cpp b/indra/llcommon/llstreamtools.cpp index 1eccfda755..1ff15fcf89 100644 --- a/indra/llcommon/llstreamtools.cpp +++ b/indra/llcommon/llstreamtools.cpp @@ -331,8 +331,7 @@ bool remove_last_char(char c, std::string& line) void unescape_string(std::string& line) { auto line_size = line.size(); - size_t index = 0; - while (index < line_size - 1) + for (size_t index = 0; line_size >= 1 && index < line_size - 1; ++index) { if ('\\' == line[index]) { @@ -347,7 +346,6 @@ void unescape_string(std::string& line) line_size--; } } - index++; } } @@ -357,8 +355,7 @@ void unescape_string(std::string& line) void escape_string(std::string& line) { auto line_size = line.size(); - size_t index = 0; - while (index < line_size) + for (size_t index = 0; index < line_size; ++index) { if ('\\' == line[index]) { @@ -372,7 +369,6 @@ void escape_string(std::string& line) line_size++; index++; } - index++; } } @@ -380,23 +376,20 @@ void escape_string(std::string& line) void replace_newlines_with_whitespace(std::string& line) { auto line_size = line.size(); - size_t index = 0; - while (index < line_size) + for (size_t index = 0; index < line_size; ++index) { if ('\n' == line[index]) { line.replace(index, 1, " "); } - index++; } } // erases any double-quote characters in 'line' void remove_double_quotes(std::string& line) { - size_t index = 0; auto line_size = line.size(); - while (index < line_size) + for (size_t index = 0; index < line_size; ) { if ('"' == line[index]) { @@ -427,19 +420,18 @@ void get_keyword_and_value(std::string& keyword, auto line_size = line.size(); size_t line_index = 0; char c; - while (line_index < line_size) + for ( ; line_index < line_size; ++line_index) { c = line[line_index]; if (!LLStringOps::isSpace(c)) { break; } - line_index++; } // get the keyword keyword.clear(); - while (line_index < line_size) + for ( ; line_index < line_size; ++line_index) { c = line[line_index]; if (LLStringOps::isSpace(c) || '\r' == c || '\n' == c) @@ -447,7 +439,6 @@ void get_keyword_and_value(std::string& keyword, break; } keyword += c; - line_index++; } // get the value @@ -465,7 +456,7 @@ void get_keyword_and_value(std::string& keyword, line_index++; } - while (line_index < line_size) + for ( ; line_index < line_size; ++line_index) { c = line[line_index]; if ('\r' == c || '\n' == c) @@ -473,7 +464,6 @@ void get_keyword_and_value(std::string& keyword, break; } value += c; - line_index++; } } } -- cgit v1.2.3 From 292bb3991b589d39d61cf721b82fe7bdae460785 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 15 Feb 2023 17:29:48 -0500 Subject: SL-18330: Fix per PR review comments. --- indra/llcommon/llstreamtools.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llcommon/llstreamtools.cpp') diff --git a/indra/llcommon/llstreamtools.cpp b/indra/llcommon/llstreamtools.cpp index 979e96b848..bc32b6fd9e 100644 --- a/indra/llcommon/llstreamtools.cpp +++ b/indra/llcommon/llstreamtools.cpp @@ -519,7 +519,7 @@ int cat_streambuf::underflow() if (gptr() == egptr()) { // here because our buffer is empty - std::streamsize size; + std::streamsize size = 0; // Until we've run out of mInputs, try reading the first of them // into mBuffer. If that fetches some characters, break the loop. while (! mInputs.empty() -- cgit v1.2.3