Skip to content

Commit 8dcfac6

Browse files
authored
Merge pull request #22168 from benrimmington/sr-6127
[stdlib] Fix memory leaks in readLine()
2 parents 21a4d54 + 7c65c14 commit 8dcfac6

File tree

3 files changed

+15
-42
lines changed

3 files changed

+15
-42
lines changed

stdlib/public/SwiftShims/LibcShims.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -57,7 +57,7 @@ __swift_size_t _swift_stdlib_fwrite_stdout(const void *ptr, __swift_size_t size,
5757

5858
// General utilities <stdlib.h>
5959
// Memory management functions
60-
static inline void _swift_stdlib_free(void *ptr) {
60+
static inline void _swift_stdlib_free(void *_Nullable ptr) {
6161
extern void free(void *);
6262
free(ptr);
6363
}

stdlib/public/core/InputStream.swift

Lines changed: 11 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -27,45 +27,18 @@ import SwiftShims
2727
/// - Returns: The string of characters read from standard input. If EOF has
2828
/// already been reached when `readLine()` is called, the result is `nil`.
2929
public func readLine(strippingNewline: Bool = true) -> String? {
30-
var linePtrVar: UnsafeMutablePointer<UInt8>?
31-
var readBytes = swift_stdlib_readLine_stdin(&linePtrVar)
32-
if readBytes == -1 {
33-
return nil
30+
var utf8Start: UnsafeMutablePointer<UInt8>?
31+
let utf8Count = swift_stdlib_readLine_stdin(&utf8Start)
32+
defer {
33+
_swift_stdlib_free(utf8Start)
3434
}
35-
_internalInvariant(readBytes >= 0,
36-
"unexpected return value from swift_stdlib_readLine_stdin")
37-
if readBytes == 0 {
38-
return ""
35+
guard utf8Count > 0 else {
36+
return nil
3937
}
40-
41-
let linePtr = linePtrVar!
42-
if strippingNewline {
43-
// FIXME: Unicode conformance. To fix this, we need to reimplement the
44-
// code we call above to get a line, since it will only stop on LF.
45-
//
46-
// <rdar://problem/20013999> Recognize Unicode newlines in readLine()
47-
//
48-
// Recognize only LF and CR+LF combinations for now.
49-
let cr = UInt8(ascii: "\r")
50-
let lf = UInt8(ascii: "\n")
51-
if readBytes == 1 && linePtr[0] == lf {
52-
return ""
53-
}
54-
if readBytes >= 2 {
55-
switch (linePtr[readBytes - 2], linePtr[readBytes - 1]) {
56-
case (cr, lf):
57-
readBytes -= 2
58-
break
59-
case (_, lf):
60-
readBytes -= 1
61-
break
62-
default:
63-
()
64-
}
65-
}
38+
let utf8Buffer = UnsafeBufferPointer(start: utf8Start, count: utf8Count)
39+
var result = String._fromUTF8Repairing(utf8Buffer).result
40+
if strippingNewline, result.last == "\n" || result.last == "\r\n" {
41+
_ = result.removeLast()
6642
}
67-
let result = String._fromUTF8Repairing(
68-
UnsafeBufferPointer(start: linePtr, count: readBytes)).0
69-
_swift_stdlib_free(linePtr)
7043
return result
7144
}

stdlib/public/stubs/Stubs.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -276,7 +276,7 @@ uint64_t swift_float80ToString(char *Buffer, size_t BufferLength,
276276

277277
/// \param[out] LinePtr Replaced with the pointer to the malloc()-allocated
278278
/// line. Can be NULL if no characters were read. This buffer should be
279-
/// freed by the caller if this function returns a positive value.
279+
/// freed by the caller.
280280
///
281281
/// \returns Size of character data returned in \c LinePtr, or -1
282282
/// if an error occurred, or EOF was reached.

0 commit comments

Comments
 (0)