Description
The following:
def foo(**opts)
end
foo("\u{0}": 1)
foo("\u{0}": true)
leads to an internal error:
Missing hash key: {#<LLVM::Module:0x1047c2120 @context=#<LLVM::Context:0x1047c2150 @unwrap=Pointer(Void)@0x12d609d60, @dispose_on_finalize=true, @disposed=false, @builders=[#<LLVM::Builder:0x105e94680 @disposed=false, @unwrap=Pointer(Void)@0x12d60bc50>]>, @unwrap=Pointer(Void)@0x12d60b300, @owned=false>, "*foo:\u0000<Bool>:Nil"} (KeyError)
from src/hash.cr:1195:9 in '[]'
from src/compiler/crystal/codegen/fun.cr:6:29 in 'typed_fun?'
from src/compiler/crystal/codegen/fun.cr:24:12 in 'target_def_fun'
from src/compiler/crystal/codegen/call.cr:435:12 in 'codegen_call'
from src/compiler/crystal/codegen/call.cr:35:7 in 'visit'
from src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
from src/compiler/crystal/codegen/codegen.cr:2403:7 in 'accept'
from src/compiler/crystal/codegen/codegen.cr:733:9 in 'visit'
from src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
from src/compiler/crystal/codegen/codegen.cr:2403:7 in 'accept'
from src/compiler/crystal/codegen/codegen.cr:76:7 in 'codegen'
from src/compiler/crystal/codegen/codegen.cr:72:5 in 'codegen:debug:frame_pointers:single_module'
from src/compiler/crystal/progress_tracker.cr:22:7 in 'codegen'
from src/compiler/crystal/compiler.cr:211:16 in 'compile'
from src/compiler/crystal/command.cr:359:3 in 'compile'
from src/compiler/crystal/command.cr:239:5 in 'run_command'
from src/compiler/crystal/command.cr:112:7 in 'run'
from src/compiler/crystal/command.cr:55:5 in 'run'
from src/compiler/crystal/command.cr:54:3 in 'run'
from src/compiler/crystal.cr:11:1 in '__crystal_main'
from src/crystal/main.cr:118:5 in 'main_user_code'
from src/crystal/main.cr:104:7 in 'main'
from src/crystal/main.cr:130:3 in 'main'
The exception is raised here:
crystal/src/compiler/crystal/codegen/fun.cr
Lines 4 to 8 in 074ec99
Here mod.functions
is an LLVM::FunctionCollection
, whose #[]?
calls LLVMGetNamedFunction
. This function takes a null-terminated string as an argument, without a way to specify the string size. Normally, when name
is *foo:\u0000<Bool>:Nil
, then this lookup should fail and #typed_fun?
should return nil
, but since there is a null byte, the name passed to LLVM becomes *foo:
, which corresponds to a previous LLVM function created for *foo:\u0000<Int32>:Nil
(this uses LLVMAddFunction
, which also takes a null-terminated string only). Hence this triggers a KeyError
when looking up @fun_types
, which does respect embedded null bytes.
Windows does not have this issue, because all non-alphanumeric characters get automatically mangled by Crystal.safe_mangling
.
Activity