[libc-commits] [libc] [libc][stdlib] Avoid scanning values during environment lookup (PR #228633)
Jeff Bailey via libc-commits
libc-commits at lists.llvm.org
Mon Oct 5 05:04:40 PDT 2026
================
@@ -82,10 +82,33 @@ cpp::optional<size_t> EnvironmentManager::find_var(cpp::string_view name) {
if (!env_array)
return cpp::nullopt;
- for (size_t i = 0; i < count; i++) {
- cpp::string_view current(env_array[i]);
- if (current.starts_with(name) && current.size() > name.size() &&
- current[name.size()] == '=')
+ // Compare entries directly: constructing a string_view from the entry's C
+ // string would scan the entire value to determine the entry's length, even
+ // when the name does not match.
+ // Empty names, supported by putenv, match entries starting with '='.
+ const char first = name.empty() ? '=' : name.front();
+
+ // Reject a leading null so matching an empty entry cannot advance past its
+ // terminator when the comparison resumes at index 1.
+ if (first == '\0')
+ return cpp::nullopt;
+ const size_t start = name.empty() ? 0 : 1;
+
+ for (size_t i = 0; i < count; ++i) {
+ const char *entry = env_array[i];
+ // Reject entries with a different first character before comparing the
+ // rest.
+ if (entry[0] != first)
+ continue;
+
+ size_t j = start;
+ // Bound the comparison by the name's length and stop at a mismatch or null
+ // terminator, so shorter entries cannot cause an out-of-bounds read.
+ while (j < name.size() && entry[j] != '\0' && entry[j] == name[j])
----------------
kaladron wrote:
Consider simplifying this with inline_strcmp (again, avoiding pointer arithmetic without overhead). This sort of pattern exists throughout the codebase:
```c++
auto comp = [](char l, char r) -> int {
return static_cast<unsigned char>(l) - static_cast<unsigned char>(r);
};
return inline_strncmp(left, right, n, comp);
```
https://github.com/llvm/llvm-project/pull/228633
More information about the libc-commits
mailing list