[tint] Fix UBU warning in lexer.cc
Moves doing math on indices where possible. Where a std::end style
pointer is needed, a helper is added to isolate the pointer math to
a single call site.
Bug: 394825124
Change-Id: I8085408ca9cfc1a00946350166835618d6f6a932
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/236214
Commit-Queue: Ryan Harrison <rharrison@chromium.org>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Auto-Submit: Ryan Harrison <rharrison@chromium.org>
diff --git a/src/tint/lang/wgsl/reader/parser/lexer.cc b/src/tint/lang/wgsl/reader/parser/lexer.cc
index 41583b0..9634504 100644
--- a/src/tint/lang/wgsl/reader/parser/lexer.cc
+++ b/src/tint/lang/wgsl/reader/parser/lexer.cc
@@ -27,6 +27,7 @@
#include "src/tint/lang/wgsl/reader/parser/lexer.h"
+#include <algorithm>
#include <cctype>
#include <charconv>
#include <cmath>
@@ -46,8 +47,6 @@
using namespace tint::core::fluent_types; // NOLINT
-TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
-
namespace tint::wgsl::reader {
namespace {
@@ -154,8 +153,8 @@
}
const char& Lexer::at(uint32_t pos) const {
- auto l = line();
- // Unlike for std::string, if pos == l.size(), indexing `l[pos]` is UB for
+ const auto& l = line();
+ // Unlike for std::string, if pos == line().size(), indexing `l[pos]` is UB for
// std::string_view.
if (pos >= l.size()) {
static const char zero = 0;
@@ -164,6 +163,14 @@
return l[pos];
}
+// This pointer is passed into std::from_chars which requires a pointer beyond the end of contiguous
+// range, not an end iterator, so will always hit this warning.
+TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
+const char* Lexer::line_end() const {
+ return &(line()[length() - 1]) + 1;
+}
+TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
+
std::string_view Lexer::substr(uint32_t offset, uint32_t count) {
return line().substr(offset, count);
}
@@ -440,14 +447,6 @@
return {};
}
- // Note, the `at` method will return a static `0` if the provided position is >= length. We
- // actually need the end pointer to point to the correct memory location to use `from_chars`.
- // So, handle the case where we point past the length specially.
- auto* end_ptr = &at(end);
- if (end >= length()) {
- end_ptr = &at(length() - 1) + 1;
- }
-
auto ret = tint::strconv::ParseDouble(std::string_view(&at(start), end - start));
double value = ret == Success ? ret.Get() : 0.0;
bool overflow =
@@ -466,7 +465,15 @@
size_t exp_value = 0;
bool exp_conversion_succeeded = true;
if (exponent_value_position.has_value()) {
- auto exp_end_ptr = end_ptr - (has_f_suffix || has_h_suffix ? 1 : 0);
+ // Note, the `at` method will return a static `0` if the provided position is >=
+ // length. The end pointer need to point to the correct memory location in the
+ // current line to use `from_chars`.
+ // So, handle the case where end points past the length specially.
+ auto exp_end = std::min(end, length()) - (has_f_suffix || has_h_suffix ? 1 : 0);
+ auto* exp_end_ptr = &at(exp_end);
+ if (exp_end >= length()) {
+ exp_end_ptr = line_end();
+ }
auto exp_ret = std::from_chars(&at(exponent_value_position.value()), exp_end_ptr,
exp_value, 10);
@@ -921,7 +928,7 @@
// characters to find the last possible and using that, we just provide the end of the string.
// We then calculate the count based off the provided end pointer and the start pointer. The
// extra `prefix_count` is to handle a `0x` which is not included in the `start` value.
- const char* end_ptr = &at(length() - 1) + 1;
+ const char* end_ptr = line_end();
int64_t value = 0;
auto res = std::from_chars(start_ptr, end_ptr, value, base);
@@ -1315,5 +1322,3 @@
}
} // namespace tint::wgsl::reader
-
-TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
diff --git a/src/tint/lang/wgsl/reader/parser/lexer.h b/src/tint/lang/wgsl/reader/parser/lexer.h
index a9c2e61..175d505 100644
--- a/src/tint/lang/wgsl/reader/parser/lexer.h
+++ b/src/tint/lang/wgsl/reader/parser/lexer.h
@@ -93,6 +93,9 @@
uint32_t length() const;
/// @returns reference to character at `pos` within current line
const char& at(uint32_t pos) const;
+ /// @returns a point to the character just beyond the end of the current line, similar to how
+ /// std::end works
+ const char* line_end() const;
/// @returns substring view at `offset` within current line of length `count`
std::string_view substr(uint32_t offset, uint32_t count);
/// advances current position by `offset` within current line