swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.58k stars 10.36k forks source link

Runtime crash when using unsafeUninitializedCapacity incorrectly #70323

Open aaron-foreflight opened 11 months ago

aaron-foreflight commented 11 months ago

Description

I accidentally attempted to access the list I was initializing in the body of the unsafeUninitializedCapacity block and found a compiler crash.

Reproduction

var myList: [Int] = Array(unsafeUninitializedCapacity: 10) { buffer, initializedCount in
            var value = 0
            initializedCount = 0
            while value < 11 {
                myList[initializedCount] = value
                initializedCount += 1
            }
        }

print(myList)

Stack dump

1.  Apple Swift version 5.9.2 (swiftlang-5.9.2.2.56 clang-1500.1.0.2.5)
2.  Compiling with the current language version
3.  While running user code "swiftcrasher.swift"
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0  swift-frontend           0x00000001037d9abc llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1  swift-frontend           0x000000010643fcb0 llvm::sys::RunSignalHandlers() + 112
2  swift-frontend           0x00000001061a9054 SignalHandler(int) + 352
3  libsystem_platform.dylib 0x000000019082ba24 _sigtramp + 56
4  libswiftCore.dylib       0x00000001a0081b40 $sSa21_makeMutableAndUniqueyyF + 128
5  libswiftCore.dylib       0x00000001a008282c $sSayxSiciM + 40
6  libswiftCore.dylib       0x00000001099d8178 $sSayxSiciM + 18446744071185979764
7  libswiftCore.dylib       0x00000001a0090d04 $sSa28_unsafeUninitializedCapacity16initializingWithSayxGSi_ySryxGz_SiztKXEtKcfC + 92
8  libswiftCore.dylib       0x00000001099d81b8 $sSa28_unsafeUninitializedCapacity16initializingWithSayxGSi_ySryxGz_SiztKXEtKcfC + 18446744071185921296
9  libswiftCore.dylib       0x00000001099d8034 $sSa28_unsafeUninitializedCapacity16initializingWithSayxGSi_ySryxGz_SiztKXEtKcfC + 18446744071185920908
10 swift-frontend           0x0000000104d8ddb8 llvm::orc::runAsMain(int (*)(int, char**), llvm::ArrayRef<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>, llvm::Optional<llvm::StringRef>) + 1276
11 swift-frontend           0x0000000100df57e8 swift::RunImmediately(swift::CompilerInstance&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, swift::IRGenOptions const&, swift::SILOptions const&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>>&&) + 11524
12 swift-frontend           0x0000000105d19c24 processCommandLineAndRunImmediately(swift::CompilerInstance&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>>&&, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, swift::FrontendObserver*, int&) + 484
13 swift-frontend           0x0000000105d21650 performCompileStepsPostSILGen(swift::CompilerInstance&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>>, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, swift::PrimarySpecificPaths const&, int&, swift::FrontendObserver*) + 1464
14 swift-frontend           0x0000000105d1cf00 performCompile(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 3020
15 swift-frontend           0x0000000105d20854 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 4568
16 swift-frontend           0x0000000105d87d44 swift::mainEntry(int, char const**) + 4408
17 dyld                     0x00000001904810e0 start + 2360
[1]    38940 segmentation fault  ./swiftcrasher.swift

Expected behavior

I expected a compiler error.

Environment

swift-driver version: 1.87.3 Apple Swift version 5.9.2 (swiftlang-5.9.2.2.56 clang-1500.1.0.2.5) Target: arm64-apple-macosx14.0

Additional information

No response

AnthonyLatsis commented 10 months ago

A simpler example:

func foo(_ fn: () -> [Int]) -> [Int] { fn() }

var x: [Int] = foo {
  var result = x
  result.append(1)
  return result
}

print(x)

SIL analyses are smart enough to reject this in a local context, but not at the top level.

Related to #69535.

Pogosito commented 9 months ago

I'll try to take it, if it's okay with anyone.

tbkka commented 9 months ago

I wasn't able to reproduce this immediately using swiftc from the command line using either the 5.9.2 compiler (from Xcode 15.2) or using a newly-built compiler from top-of-tree. Can anyone provide more details on how to reproduce this?

AnthonyLatsis commented 9 months ago

Speaking of the original example, I can reproduce a segfault with both a swiftc-emitted binary and the interpreter, using a 6d66211dea41ca6 compiler:

AnthonyLatsis commented 8 months ago

More examples from dupes:

let x: Any = x

print(a)  // Outputs "0" or "45" with -O
let a = 45

cc @atrick

vojtarylko commented 8 months ago

There is a discussion about variables in top-level code from 2021 (without clear conclusion) – https://forums.swift.org/t/on-the-behavior-of-variables-in-top-level-code/52230

atrick commented 7 months ago

Note that the stack dump says: While running user code "swiftcrasher.swift"

atrick commented 7 months ago

This looks like https://github.com/apple/swift/issues/70356

Which is just one manifestation of the fact that Swift top-level code is fundamentally broken, and could be fixed simply by treating top-level variables as locals.