Sorbet: Sorbet crash on strict run

Created on 21 Jun 2019  路  4Comments  路  Source: sorbet/sorbet

Input

Running on https://github.com/envato/stack_master/

bundle exec init
bundle exec srb tc --typed=strict --error-white-list=7017 --autocorrect --max-threads 1 lib

(path doesn't matter - the crash happens on any file)

Observed output

Crashed with

Process:               sorbet [55428]
Path:                  /Users/USER/*/sorbet
Identifier:            sorbet
Version:               0
Code Type:             X86-64 (Native)
Parent Process:        ??? [55410]
Responsible:           sorbet [55428]
User ID:               501

Date/Time:             2019-06-21 12:41:54.972 +1000
OS Version:            Mac OS X 10.14.5 (18F132)
Report Version:        12
Bridge OS Version:     3.0 (14Y901)
Anonymous UUID:        302BD017-6DC3-5877-EF8B-3170B539091D

Sleep/Wake UUID:       D9DD5559-56A7-4748-BC9A-7F0A92F37BFE

Time Awake Since Boot: 84000 seconds
Time Since Wake:       12000 seconds

System Integrity Protection: enabled

Crashed Thread:        1  typecheck

Exception Type:        EXC_BAD_ACCESS (SIGBUS)
Exception Codes:       KERN_PROTECTION_FAILURE at 0x000000010056fde0
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Bus error: 10
Termination Reason:    Namespace SIGNAL, Code 0xa
Terminating Process:   exc handler [55428]

VM Regions Near 0x10056fde0:
--> __TEXT                 0000000100000000-00000001006dd000 [ 7028K] r-x/rwx SM=COW  /Users/USER/*
    __DATA                 00000001006dd000-00000001006fa000 [  116K] rw-/rwx SM=COW  /Users/USER/*

Application Specific Information:
dyld2 mode

Thread 0:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib          0x00007fff5891227e semaphore_timedwait_trap + 10
1   sorbet                          0x0000000100041f76 moodycamel::details::mpmc_sema::LightweightSemaphore::waitWithPartialSpinning(long long) + 150
2   sorbet                          0x000000010011ba37 DequeueResult AbstractConcurrentBoundedQueue<sorbet::realmain::pipeline::typecheck_thread_result, moodycamel::BlockingConcurrentQueue<sorbet::realmain::pipeline::typecheck_thread_result, moodycamel::ConcurrentQueueDefaultTraits> >::wait_pop_timed<long long, std::__1::ratio<1l, 1000l> >(sorbet::realmain::pipeline::typecheck_thread_result&, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000l> > const&, spdlog::logger&) + 103
3   sorbet                          0x000000010011ac9f sorbet::realmain::pipeline::typecheck(std::__1::unique_ptr<sorbet::core::GlobalState, std::__1::default_delete<sorbet::core::GlobalState> >&, std::__1::vector<sorbet::ast::ParsedFile, std::__1::allocator<sorbet::ast::ParsedFile> >, sorbet::realmain::options::Options const&, sorbet::WorkerPool&) + 863
4   sorbet                          0x0000000100006085 sorbet::realmain::realmain(int, char**) + 7637
5   sorbet                          0x00000001000021eb main + 11
6   libdyld.dylib                   0x00007fff587dd3d5 start + 1

Thread 1 Crashed:: typecheck
0   sorbet                          0x0000000100502f90 sorbet::core::(anonymous namespace)::Module_tripleEq::apply(sorbet::core::Context, sorbet::core::DispatchArgs, sorbet::core::Type const*) const + 64
1   sorbet                          0x00000001004effd6 sorbet::core::dispatchCallSymbol(sorbet::core::Context, sorbet::core::DispatchArgs, sorbet::core::Type const*, sorbet::core::SymbolRef, std::__1::vector<sorbet::core::TypePtr, std::__1::allocator<sorbet::core::TypePtr> >&) + 14086
2   sorbet                          0x00000001004f486a sorbet::core::ClassType::dispatchCall(sorbet::core::Context, sorbet::core::DispatchArgs) + 138
3   sorbet                          0x00000001002e99bd sorbet::infer::SigSuggestion::maybeSuggestSig(sorbet::core::Context, sorbet::core::ErrorBuilder&, std::__1::unique_ptr<sorbet::cfg::CFG, std::__1::default_delete<sorbet::cfg::CFG> >&, sorbet::core::TypePtr const&, sorbet::core::TypeConstraint&) + 5069
4   sorbet                          0x000000010030b449 sorbet::infer::Inference::run(sorbet::core::Context, std::__1::unique_ptr<sorbet::cfg::CFG, std::__1::default_delete<sorbet::cfg::CFG> >) + 7385
5   sorbet                          0x000000010012526f sorbet::realmain::pipeline::CFGCollectorAndTyper::preTransformMethodDef(sorbet::core::Context, std::__1::unique_ptr<sorbet::ast::MethodDef, std::__1::default_delete<sorbet::ast::MethodDef> >) + 255
6   sorbet                          0x00000001001239de sorbet::ast::TreeMapper<sorbet::realmain::pipeline::CFGCollectorAndTyper, sorbet::core::Context>::mapMethodDef(std::__1::unique_ptr<sorbet::ast::MethodDef, std::__1::default_delete<sorbet::ast::MethodDef> >, sorbet::core::Context) + 78
7   sorbet                          0x00000001001230f7 sorbet::ast::TreeMapper<sorbet::realmain::pipeline::CFGCollectorAndTyper, sorbet::core::Context>::mapIt(std::__1::unique_ptr<sorbet::ast::Expression, std::__1::default_delete<sorbet::ast::Expression> >, sorbet::core::Context) + 663
8   sorbet                          0x00000001001240d7 sorbet::ast::TreeMapper<sorbet::realmain::pipeline::CFGCollectorAndTyper, sorbet::core::Context>::mapClassDef(std::__1::unique_ptr<sorbet::ast::ClassDef, std::__1::default_delete<sorbet::ast::ClassDef> >, sorbet::core::Context) + 151
9   sorbet                          0x00000001001231d4 sorbet::ast::TreeMapper<sorbet::realmain::pipeline::CFGCollectorAndTyper, sorbet::core::Context>::mapIt(std::__1::unique_ptr<sorbet::ast::Expression, std::__1::default_delete<sorbet::ast::Expression> >, sorbet::core::Context) + 884
10  sorbet                          0x0000000100123cf1 sorbet::ast::TreeMapper<sorbet::realmain::pipeline::CFGCollectorAndTyper, sorbet::core::Context>::mapInsSeq(std::__1::unique_ptr<sorbet::ast::InsSeq, std::__1::default_delete<sorbet::ast::InsSeq> >, sorbet::core::Context) + 145
11  sorbet                          0x000000010012313e sorbet::ast::TreeMapper<sorbet::realmain::pipeline::CFGCollectorAndTyper, sorbet::core::Context>::mapIt(std::__1::unique_ptr<sorbet::ast::Expression, std::__1::default_delete<sorbet::ast::Expression> >, sorbet::core::Context) + 734
12  sorbet                          0x0000000100118a06 std::__1::unique_ptr<sorbet::ast::Expression, std::__1::default_delete<sorbet::ast::Expression> > sorbet::ast::TreeMap::apply<sorbet::core::Context, sorbet::realmain::pipeline::CFGCollectorAndTyper>(sorbet::core::Context, sorbet::realmain::pipeline::CFGCollectorAndTyper&, std::__1::unique_ptr<sorbet::ast::Expression, std::__1::default_delete<sorbet::ast::Expression> >) + 70
13  sorbet                          0x00000001001184da sorbet::realmain::pipeline::typecheckOne(sorbet::core::Context, sorbet::ast::ParsedFile, sorbet::realmain::options::Options const&) + 1482
14  sorbet                          0x0000000100129f2c std::__1::__function::__func<sorbet::realmain::pipeline::typecheck(std::__1::unique_ptr<sorbet::core::GlobalState, std::__1::default_delete<sorbet::core::GlobalState> >&, std::__1::vector<sorbet::ast::ParsedFile, std::__1::allocator<sorbet::ast::ParsedFile> >, sorbet::realmain::options::Options const&, sorbet::WorkerPool&)::$_3, std::__1::allocator<sorbet::realmain::pipeline::typecheck(std::__1::unique_ptr<sorbet::core::GlobalState, std::__1::default_delete<sorbet::core::GlobalState> >&, std::__1::vector<sorbet::ast::ParsedFile, std::__1::allocator<sorbet::ast::ParsedFile> >, sorbet::realmain::options::Options const&, sorbet::WorkerPool&)::$_3>, void ()>::operator()() + 284
15  sorbet                          0x0000000100528f65 std::__1::__function::__func<sorbet::WorkerPoolImpl::multiplexJob(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::function<void ()>)::$_2, std::__1::allocator<sorbet::WorkerPoolImpl::multiplexJob(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::function<void ()>)::$_2>, bool ()>::operator()() + 37
16  sorbet                          0x00000001005284f5 std::__1::__function::__func<sorbet::WorkerPoolImpl::WorkerPoolImpl(int, spdlog::logger&)::$_0, std::__1::allocator<sorbet::WorkerPoolImpl::WorkerPoolImpl(int, spdlog::logger&)::$_0>, void ()>::operator()() + 325
17  sorbet                          0x0000000100545bd4 Joinable::trampoline(void*) + 68
18  libsystem_pthread.dylib         0x00007fff589d12eb _pthread_body + 126
19  libsystem_pthread.dylib         0x00007fff589d4249 _pthread_start + 66
20  libsystem_pthread.dylib         0x00007fff589d040d thread_start + 13

Thread 1 crashed with X86 Thread State (64-bit):
  rax: 0x000000010056fdd8  rbx: 0x00000001045bf2d8  rcx: 0x00000001045bf2d8  rdx: 0x000070000f419448
  rdi: 0x000000010330d6f0  rsi: 0x00000001006f82c8  rbp: 0x000070000f4192a0  rsp: 0x000070000f419220
   r8: 0xc4ceb9fe1a85ec53   r9: 0xff51afd7ed558ccd  r10: 0x0000000100d710b0  r11: 0x0000000100e015b0
  r12: 0x000070000f419810  r13: 0x000070000f419f30  r14: 0x000070000f419610  r15: 0x000070000f419448
  rip: 0x0000000100502f90  rfl: 0x0000000000010206  cr2: 0x000000010056fde0

Logical CPU:     4
Error Code:      0x00000007
Trap Number:     14

Running on osx 10.14.5
Sorbet version 0.4.4269 (installed as sorbet-static 0.4.4269-universal-darwin-14)

bug

Most helpful comment

This seems to be enough to reproduce the issue:

# typed: strict
module StackMaster
  class ParameterResolver
    def resolve_parameter_value(key, parameter_value)
      return parameter_value unless Hash === parameter_value
    end
  end
end

It passes without strict.

All 4 comments

Thanks for the report. It would be amazing if you could bisect your codebase until the problem reproduces on a single file. Just keep deleting files (or put # typed: ignore at the top) and run srb tc with the flags mentioned above until the error goes away, with the goal of trying to delete all but one file.

The crash happens in a function in Sorbet called Module_tripleEq. Sorbet was trying to do type inference in one method in one file that used either === directly or indirectly via a case statement, and something invalidated an assumption that were making. So I have high confidence that this should be trackable to a very small repro.

This seems to be enough to reproduce the issue:

# typed: strict
module StackMaster
  class ParameterResolver
    def resolve_parameter_value(key, parameter_value)
      return parameter_value unless Hash === parameter_value
    end
  end
end

It passes without strict.

@viraptor The fix for this is in master now. After it builds and publishes, you should be able to try again.

Version 0.4.4282 will be the version you're looking for.

Was this page helpful?
0 / 5 - 0 ratings