Skip to content

Commit f7a73de

Browse files
committed
Fix pos() reset to clear zero-length /g guard
1 parent bbcbdfd commit f7a73de

File tree

1 file changed

+55
-1
lines changed

1 file changed

+55
-1
lines changed

src/main/java/org/perlonjava/runtime/RuntimePosLvalue.java

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public static RuntimeScalar pos(RuntimeScalar perlVariable) {
4949
if (cachedEntry == null || cachedEntry.valueHash != code) {
5050
// If the position is not cached or the value has changed,
5151
// create a new undefined RuntimeScalar to represent the position
52-
position = new RuntimeScalar();
52+
position = new PosLvalueScalar(perlVariable);
5353
// Cache the new position with the current hash of the value
5454
positionCache.put(perlVariable, new CacheEntry(code, position));
5555
} else {
@@ -59,6 +59,60 @@ public static RuntimeScalar pos(RuntimeScalar perlVariable) {
5959
return position;
6060
}
6161

62+
private static void clearZeroLengthMatchTracking(RuntimeScalar perlVariable) {
63+
CacheEntry cachedEntry = positionCache.get(perlVariable);
64+
if (cachedEntry != null) {
65+
cachedEntry.lastMatchWasZeroLength = false;
66+
cachedEntry.lastMatchPosition = -1;
67+
cachedEntry.lastMatchPattern = null;
68+
}
69+
}
70+
71+
private static class PosLvalueScalar extends RuntimeScalar {
72+
private final RuntimeScalar target;
73+
74+
private PosLvalueScalar(RuntimeScalar target) {
75+
super();
76+
this.target = target;
77+
}
78+
79+
@Override
80+
public RuntimeScalar set(RuntimeScalar value) {
81+
RuntimePosLvalue.clearZeroLengthMatchTracking(target);
82+
return super.set(value);
83+
}
84+
85+
@Override
86+
public RuntimeScalar set(int value) {
87+
RuntimePosLvalue.clearZeroLengthMatchTracking(target);
88+
return super.set(value);
89+
}
90+
91+
@Override
92+
public RuntimeScalar set(long value) {
93+
RuntimePosLvalue.clearZeroLengthMatchTracking(target);
94+
return super.set(value);
95+
}
96+
97+
@Override
98+
public RuntimeScalar set(boolean value) {
99+
RuntimePosLvalue.clearZeroLengthMatchTracking(target);
100+
return super.set(value);
101+
}
102+
103+
@Override
104+
public RuntimeScalar set(String value) {
105+
RuntimePosLvalue.clearZeroLengthMatchTracking(target);
106+
return super.set(value);
107+
}
108+
109+
@Override
110+
public RuntimeScalar set(Object value) {
111+
RuntimePosLvalue.clearZeroLengthMatchTracking(target);
112+
return super.set(value);
113+
}
114+
}
115+
62116
/**
63117
* Check if the last match at this position was zero-length with the given pattern.
64118
* This is used to prevent infinite loops in global regex matches.

0 commit comments

Comments
 (0)