Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

String literals are mutable in the interpreter #12422

Open
HertzDevil opened this issue Aug 28, 2022 · 0 comments
Open

String literals are mutable in the interpreter #12422

HertzDevil opened this issue Aug 28, 2022 · 0 comments
Labels
kind:bug A bug in the code. Does not apply to documentation, specs, etc. status:discussion topic:compiler:interpreter

Comments

@HertzDevil
Copy link
Contributor

HertzDevil commented Aug 28, 2022

Examples:

icr:1:0> a = "abc"
=> "abc"
icr:2:0> b = a
=> "abc"
icr:3:0> a.to_unsafe.value = 33_u8
=> 33
icr:4:0> a
=> "!bc"
icr:5:0> b
=> "!bc"
icr:1:0> 1.class.name.to_unsafe.value = 33_u8
=> 33
icr:2:0> 1.class.name
=> Error while calling inspect on value: instantiating 'String#inspect()'
"!nt32"
icr:3:0> 1.class.name
=> Error while calling inspect on value: 
"!nt32"
icr:4:0> 1.class.name
=> Invalid memory access (signal 11) at address 0x0
[0x55bcc21fff56] *Exception::CallStack::print_backtrace:Nil +118 in /home/quinton/crystal/crystal/.build/crystal
[0x55bcc21d6496] ~procProc(Int32, Pointer(LibC::SiginfoT), Pointer(Void), Nil) +310 in /home/quinton/crystal/crystal/.build/crystal
[0x7f81ba83daf0] ?? +140195156712176 in /lib/x86_64-linux-gnu/libc.so.6
[0x55bcc30711aa] *Crystal::Repl::Interpreter#interpret<Crystal::ASTNode+, Crystal::Type+>:Crystal::Repl::Value +2330 in /home/quinton/crystal/crystal/.build/crystal
[0x55bcc306fe7c] *Crystal::Repl::Interpreter#interpret<Crystal::ASTNode+, Hash(String, Crystal::MetaVar)>:Crystal::Repl::Value +2284 in /home/quinton/crystal/crystal/.build/crystal
[0x55bcc3404b23] *Crystal::Repl::Value#to_s<IO::FileDescriptor>:(IO::FileDescriptor | Nil) +931 in /home/quinton/crystal/crystal/.build/crystal
[0x55bcc237d743] *IO::FileDescriptor +67 in /home/quinton/crystal/crystal/.build/crystal
[0x55bcc237d6ed] *IO::FileDescriptor +77 in /home/quinton/crystal/crystal/.build/crystal
[0x55bcc21d13c9] *puts<Crystal::Repl::Value>:Nil +137 in /home/quinton/crystal/crystal/.build/crystal
[0x55bcc33f9601] *Crystal::Repl::Prompt#display<Crystal::Repl::Value>:Nil +81 in /home/quinton/crystal/crystal/.build/crystal
[0x55bcc363a661] *Crystal::Repl#run:Nil +673 in /home/quinton/crystal/crystal/.build/crystal
[0x55bcc357cb0a] *Crystal::Command#repl:(Crystal::Repl::Value | Nil) +1226 in /home/quinton/crystal/crystal/.build/crystal
[0x55bcc3577401] *Crystal::Command#run:(Bool | Crystal::Repl::Value | Nil) +1409 in /home/quinton/crystal/crystal/.build/crystal
[0x55bcc3576cfb] *Crystal::Command::run<Array(String)>:(Bool | Crystal::Repl::Value | Nil) +43 in /home/quinton/crystal/crystal/.build/crystal
[0x55bcc3576c6e] *Crystal::Command::run:(Bool | Crystal::Repl::Value | Nil) +46 in /home/quinton/crystal/crystal/.build/crystal
[0x55bcc21b5987] __crystal_main +2583 in /home/quinton/crystal/crystal/.build/crystal
[0x55bcc23a1783] *Crystal::main_user_code<Int32, Pointer(Pointer(UInt8))>:Nil +19 in /home/quinton/crystal/crystal/.build/crystal
[0x55bcc23a16ea] *Crystal::main<Int32, Pointer(Pointer(UInt8))>:Int32 +58 in /home/quinton/crystal/crystal/.build/crystal
[0x55bcc21c2f36] main +6 in /home/quinton/crystal/crystal/.build/crystal
[0x7f81ba82920a] ?? +140195156627978 in /lib/x86_64-linux-gnu/libc.so.6
[0x7f81ba8292bc] __libc_start_main +124 in /lib/x86_64-linux-gnu/libc.so.6
[0x55bcc21b4ea1] _start +33 in /home/quinton/crystal/crystal/.build/crystal
[0x0] ???
Segmentation fault

It seems there is some kind of stack corruption for the second example too.

To fix this we should probably simulate read-only memory in the interpreter; even crashing on the pointer write, like in compiled mode, is better than introducing undefined behavior that only gets picked up later. This might also be necessary if we want to be able to form pointers to constants (e.g. #12396).

@HertzDevil HertzDevil added status:discussion topic:compiler:interpreter kind:bug A bug in the code. Does not apply to documentation, specs, etc. labels Aug 28, 2022
straight-shoota pushed a commit that referenced this issue Mar 2, 2025
This works by adding a specialized cache for the results of `pointerof` expressions that have the form `pointerof($Slice:n.@buffer)`, which can only arise from literal expansion of `Slice.literal` calls during the semantic phase.

As with string literals, the contents of slice literals are not truly read-only at the moment (#12422).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:bug A bug in the code. Does not apply to documentation, specs, etc. status:discussion topic:compiler:interpreter
Projects
None yet
Development

No branches or pull requests

1 participant