Skip to content

Commit 5ec215b

Browse files
committed
Fix vivify() crash in NonStrict methods for read-only scalars
This fixes the crash 'Modification of a read-only value attempted' when using symbolic references like ${"\!"}{ENOENT}. For RuntimeScalarReadOnly (immutable scalars), lvalue is null. When NonStrict methods are called, we now delegate to super instead of calling vivify(), which allows symbolic references to work without trying to modify read-only values. Result: magic.t now passes 158/208 tests (was crashing at 103) Known issue: Double symbolic dereference like ${"foo"}{key} still returns empty. This needs further investigation.
1 parent e7029c9 commit 5ec215b

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

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

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -201,33 +201,51 @@ public RuntimeScalar hashDerefExists(RuntimeScalar index) {
201201
}
202202

203203
// Non-strict versions (allow symbolic references)
204+
// Note: We don't call vivify() here because for symbolic references (STRING/BYTE_STRING),
205+
// we're not modifying the scalar - we're just using its string value to look up a global variable.
206+
// For RuntimeScalarReadOnly (immutable scalars like string literals), lvalue is null and we can't vivify.
207+
// Instead, we call the method directly on 'this' which will handle symbolic references correctly.
204208
public RuntimeScalar hashDerefGetNonStrict(RuntimeScalar index, String currentPackage) {
205-
vivify();
209+
if (lvalue == null) {
210+
// For read-only scalars, call the method on 'this' directly
211+
// This will use the RuntimeScalar implementation which handles symbolic references
212+
return super.hashDerefGetNonStrict(index, currentPackage);
213+
}
206214
return lvalue.hashDerefGetNonStrict(index, currentPackage);
207215
}
208216

209217
public RuntimeScalar hashDerefDeleteNonStrict(RuntimeScalar index, String currentPackage) {
210-
vivify();
218+
if (lvalue == null) {
219+
return super.hashDerefDeleteNonStrict(index, currentPackage);
220+
}
211221
return lvalue.hashDerefDeleteNonStrict(index, currentPackage);
212222
}
213223

214224
public RuntimeScalar hashDerefExistsNonStrict(RuntimeScalar index, String currentPackage) {
215-
vivify();
225+
if (lvalue == null) {
226+
return super.hashDerefExistsNonStrict(index, currentPackage);
227+
}
216228
return lvalue.hashDerefExistsNonStrict(index, currentPackage);
217229
}
218230

219231
public RuntimeScalar arrayDerefGetNonStrict(RuntimeScalar index, String currentPackage) {
220-
vivify();
232+
if (lvalue == null) {
233+
return super.arrayDerefGetNonStrict(index, currentPackage);
234+
}
221235
return lvalue.arrayDerefGetNonStrict(index, currentPackage);
222236
}
223237

224238
public RuntimeScalar arrayDerefDeleteNonStrict(RuntimeScalar index, String currentPackage) {
225-
vivify();
239+
if (lvalue == null) {
240+
return super.arrayDerefDeleteNonStrict(index, currentPackage);
241+
}
226242
return lvalue.arrayDerefDeleteNonStrict(index, currentPackage);
227243
}
228244

229245
public RuntimeScalar arrayDerefExistsNonStrict(RuntimeScalar index, String currentPackage) {
230-
vivify();
246+
if (lvalue == null) {
247+
return super.arrayDerefExistsNonStrict(index, currentPackage);
248+
}
231249
return lvalue.arrayDerefExistsNonStrict(index, currentPackage);
232250
}
233251

0 commit comments

Comments
 (0)