From 5ed1f93b0e87d961282a4487c81b48cf6f0b127f Mon Sep 17 00:00:00 2001 From: Satoshi Tagomori Date: Fri, 8 May 2026 18:43:15 +0900 Subject: Fix bug: the Slowpath doesn't work correctly because of double increment builtin_lookup() find the pre-loaded and compiled (to ISeq) builtin libraries. The libraries (.rb files) are loaded by miniruby, and those ISeq are written in build/builtin_library.rbbin in the order that miniruby loads. The fastpath of builtin_lookup() searches the contents of builtin_library.rbbin in the order of miniruby loading, on ruby. The only fastpath works as far as the order of loading libraries in ruby is equal to miniruby. This is the reason why the slowpath's bug has not caused problems. The slowpath incremented `bb` twice in a loop, so it's clearly bug to skip the item after checking bb. Items at 1, 3, 5... will never be found in the swlopath. --- builtin.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/builtin.c b/builtin.c index 6cc9790466..7861aee8ba 100644 --- a/builtin.c +++ b/builtin.c @@ -22,13 +22,36 @@ bin4feature(const struct builtin_binary *bb, const char *feature, size_t *psize) static const unsigned char* builtin_lookup(const char *feature, size_t *psize) { - static int index = 0; - const unsigned char *bin = bin4feature(&builtin_binary[index++], feature, psize); + static size_t index = 0; + const unsigned char *bin = NULL; + + /* + * Fast path: + * builtin_binary is usually arranged in the same order + * as features are looked up in miniruby, so try the next entry first. + */ + if (builtin_binary[index].feature) { + bin = bin4feature(&builtin_binary[index], feature, psize); + index++; + } + if (bin) { + return bin; + } - // usually, `builtin_binary` order is loading order at miniruby. - for (const struct builtin_binary *bb = &builtin_binary[0]; bb->feature &&! bin; bb++) { - bin = bin4feature(bb++, feature, psize); + /* + * Fallback: + * In case the lookup order does not match the array order, + * scan the entire table to find the feature. + */ + for (const struct builtin_binary *bb = &builtin_binary[0]; + bb->feature; + bb++) { + bin = bin4feature(bb, feature, psize); + if (bin) { + break; + } } + return bin; } -- cgit v1.2.3