Skip to content

Internal error when using null characters in call argument names #14786

Open
@HertzDevil

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:

def typed_fun?(mod : LLVM::Module, name : String) : LLVMTypedFunction?
if func = mod.functions[name]?
LLVMTypedFunction.new(@fun_types[{mod, name}], func)
end
end

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    kind:bugA bug in the code. Does not apply to documentation, specs, etc.topic:compiler:codegen

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions