47 lines
1.7 KiB
Diff
47 lines
1.7 KiB
Diff
# UNDF: UNDF-2026-000000210
|
|
--- a/pad.h
|
|
+++ b/pad.h
|
|
@@ -162,6 +162,8 @@ struct padnamelist {
|
|
SSize_t xpadnl_fill;
|
|
SSize_t xpadnl_max;
|
|
SSize_t xpadnl_max_named;
|
|
+ /* CWE-407 fix: string→offset hash for O(1) named-variable lookup */
|
|
+ HV *xpadnl_namehash;
|
|
U32 xpadnl_refcnt;
|
|
};
|
|
|
|
--- a/pad.c
|
|
+++ b/pad.c
|
|
@@ -543,6 +543,14 @@ Perl_pad_alloc_name(pTHX_ PADNAME *name, U32 flags, HV *typestash, HV *ourstash
|
|
padnamelist_store(PL_comppad_name, offset, name);
|
|
+
|
|
+ /* CWE-407 fix: record name → offset in the namehash for O(1) findlex */
|
|
+ if (PadnamePV(name) && !PadnameOUTER(name)) {
|
|
+ if (!PadnamelistNAMEHASH(PL_comppad_name))
|
|
+ PadnamelistNAMEHASH(PL_comppad_name) = newHV();
|
|
+ (void)hv_store(PadnamelistNAMEHASH(PL_comppad_name),
|
|
+ PadnamePV(name), PadnameLEN(name),
|
|
+ newSVuv((UV)offset), 0);
|
|
+ }
|
|
|
|
@@ -1168,6 +1176,18 @@ S_pad_findlex(...)
|
|
if (padlist) { /* not an undef CV */
|
|
PADOFFSET fake_offset = 0;
|
|
const PADNAMELIST * const names = PadlistNAMES(padlist);
|
|
PADNAME * const * const name_p = PadnamelistARRAY(names);
|
|
|
|
+ /* CWE-407 fix: O(1) hash lookup before the O(n) linear scan */
|
|
+ HV *nh = PadnamelistNAMEHASH(names);
|
|
+ if (nh) {
|
|
+ SV **svp = hv_fetch(nh, namepv, (I32)namelen, 0);
|
|
+ if (svp) {
|
|
+ PADOFFSET candidate = (PADOFFSET)SvUV(*svp);
|
|
+ const PADNAME *cn = name_p[candidate];
|
|
+ if (cn && !PadnameOUTER(cn) && PadnameIN_SCOPE(cn, seq)) {
|
|
+ offset = candidate;
|
|
+ goto found;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
for (offset = PadnamelistMAXNAMED(names); offset > 0; offset--) {
|