authorgravatar for twostepted@gmail.comTravis Staloch <twostepted@gmail.com> 2024-04-30 17:21:44-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-02 22:09:03-07:00
log44db92d1ca90c9cfdfb29fe46f04ff8f11c80901
tree713c0d3e47f69e9b4979c396934a5c4783f29901
parentea9d817a905ae19dcf27db4f380270485f9e26d2

std.StaticStringMap: bump eval branch quota

closes #19803 by changing quota from (30 * N) to (10 * N * log2(N)) where N = kvs_list.len * adds reported adversarial test case * update doc comment of getLongestPrefix()

1 files changed, 39 insertions(+), 4 deletions(-)

lib/std/static_string_map.zig+39-4
......@@ -70,11 +70,15 @@ pub fn StaticStringMapWithEql(
7070 /// (only keys) tuples if `V` is `void`.
7171 pub inline fn initComptime(comptime kvs_list: anytype) Self {
7272 comptime {
73 @setEvalBranchQuota(30 * kvs_list.len);
7473 var self = Self{};
7574 if (kvs_list.len == 0)
7675 return self;
7776
77 // Since the KVs are sorted, a linearly-growing bound will never
78 // be sufficient for extreme cases. So we grow proportional to
79 // N*log2(N).
80 @setEvalBranchQuota(10 * kvs_list.len * std.math.log2_int_ceil(usize, kvs_list.len));
81
7882 var sorted_keys: [kvs_list.len][]const u8 = undefined;
7983 var sorted_vals: [kvs_list.len]V = undefined;
8084
......@@ -212,8 +216,12 @@ pub fn StaticStringMapWithEql(
212216 }
213217 }
214218
215 /// Returns the longest key, value pair where key is a prefix of `str`
219 /// Returns the key-value pair where key is the longest prefix of `str`
216220 /// else null.
221 ///
222 /// This is effectively an O(N) algorithm which loops from `max_len` to
223 /// `min_len` and calls `getIndex()` to check all keys with the given
224 /// len.
217225 pub fn getLongestPrefix(self: Self, str: []const u8) ?KV {
218226 if (self.kvs.len == 0)
219227 return null;
......@@ -497,6 +505,33 @@ test "getLongestPrefix2" {
497505 try testing.expectEqual(null, map.getLongestPrefix("xxx"));
498506}
499507
500test "long kvs_list doesn't exceed @setEvalBranchQuota" {
501 _ = TestMapVoid.initComptime([1]TestKVVoid{.{"x"}} ** 1_000);
508test "sorting kvs doesn't exceed eval branch quota" {
509 // from https://github.com/ziglang/zig/issues/19803
510 const TypeToByteSizeLUT = std.StaticStringMap(u32).initComptime(.{
511 .{ "bool", 0 },
512 .{ "c_int", 0 },
513 .{ "c_long", 0 },
514 .{ "c_longdouble", 0 },
515 .{ "t20", 0 },
516 .{ "t19", 0 },
517 .{ "t18", 0 },
518 .{ "t17", 0 },
519 .{ "t16", 0 },
520 .{ "t15", 0 },
521 .{ "t14", 0 },
522 .{ "t13", 0 },
523 .{ "t12", 0 },
524 .{ "t11", 0 },
525 .{ "t10", 0 },
526 .{ "t9", 0 },
527 .{ "t8", 0 },
528 .{ "t7", 0 },
529 .{ "t6", 0 },
530 .{ "t5", 0 },
531 .{ "t4", 0 },
532 .{ "t3", 0 },
533 .{ "t2", 0 },
534 .{ "t1", 1 },
535 });
536 try testing.expectEqual(1, TypeToByteSizeLUT.get("t1"));
502537}