Skip to content

Commit de015c6

Browse files
authored
Unify asprintf/vasprintf implementations and make them truly portable by using vsnprintf (swiftlang#39314)
1 parent aeda34e commit de015c6

File tree

6 files changed

+36
-98
lines changed

6 files changed

+36
-98
lines changed

include/swift/Runtime/Portability.h

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,36 +29,41 @@ size_t _swift_strlcpy(char *dst, const char *src, size_t maxlen);
2929
SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE
3030
#endif
3131
#ifdef __clang__
32-
__attribute((__format__(__printf__, 2, 3)))
32+
__attribute((__format__(__printf__, 2, 0)))
3333
#endif
3434
inline static int
35-
swift_asprintf(char **strp, const char *fmt, ...) {
36-
va_list args;
37-
va_start(args, fmt);
38-
#if defined(_WIN32)
39-
#pragma GCC diagnostic push
40-
#pragma GCC diagnostic ignored "-Wuninitialized"
41-
int len = _vscprintf(fmt, args);
42-
#pragma GCC diagnostic pop
43-
if (len < 0) {
44-
va_end(args);
35+
swift_vasprintf(char **strp, const char *fmt, va_list args) {
36+
va_list args_for_len;
37+
va_copy(args_for_len, args);
38+
int len = vsnprintf(nullptr, 0, fmt, args_for_len);
39+
va_end(args_for_len);
40+
41+
if (len < 0)
4542
return -1;
46-
}
47-
char *buffer = static_cast<char *>(malloc(len + 1));
48-
if (!buffer) {
49-
va_end(args);
43+
char *buffer = reinterpret_cast<char *>(malloc(len + 1));
44+
if (!buffer)
5045
return -1;
51-
}
5246
int result = vsprintf(buffer, fmt, args);
5347
if (result < 0) {
54-
va_end(args);
5548
free(buffer);
5649
return -1;
5750
}
5851
*strp = buffer;
59-
#else
60-
int result = vasprintf(strp, fmt, args);
52+
return result;
53+
}
54+
55+
// Skip the attribute when included by the compiler.
56+
#ifdef SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE
57+
SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE
58+
#endif
59+
#ifdef __clang__
60+
__attribute((__format__(__printf__, 2, 3)))
6161
#endif
62+
inline static int
63+
swift_asprintf(char **strp, const char *fmt, ...) {
64+
va_list args;
65+
va_start(args, fmt);
66+
int result = swift_vasprintf(strp, fmt, args);
6267
va_end(args);
6368
return result;
6469
}

lib/SwiftDemangle/MangleHack.cpp

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,50 +18,25 @@
1818
//===----------------------------------------------------------------------===//
1919

2020
#include "swift/SwiftDemangle/MangleHack.h"
21+
#include "swift/Runtime/Portability.h"
2122
#include "swift/Strings.h"
2223
#include <cassert>
2324
#include <cstdarg>
2425
#include <cstdio>
2526
#include <cstdlib>
2627
#include <cstring>
2728

28-
#if defined(_WIN32)
29-
static int vasprintf(char **strp, const char *fmt, va_list ap) {
30-
int len = _vscprintf(fmt, ap);
31-
if (len < 0)
32-
return len;
33-
char *buffer = static_cast<char *>(malloc(len + 1));
34-
if (buffer == nullptr)
35-
return -1;
36-
int result = vsprintf(buffer, fmt, ap);
37-
if (result < 0) {
38-
free(buffer);
39-
return -1;
40-
}
41-
*strp = buffer;
42-
return result;
43-
}
44-
45-
static int asprintf(char **strp, const char *fmt, ...) {
46-
va_list args;
47-
va_start(args, fmt);
48-
int result = vasprintf(strp, fmt, args);
49-
va_end(args);
50-
return result;
51-
}
52-
#endif
53-
5429
const char *
5530
_swift_mangleSimpleClass(const char *module, const char *class_) {
5631
size_t moduleLength = strlen(module);
5732
size_t classLength = strlen(class_);
5833
char *value = nullptr;
5934
if (swift::STDLIB_NAME == llvm::StringRef(module)) {
60-
int result = asprintf(&value, "_TtCs%zu%s", classLength, class_);
35+
int result = swift_asprintf(&value, "_TtCs%zu%s", classLength, class_);
6136
assert(result > 0);
6237
(void)result;
6338
} else {
64-
int result = asprintf(&value, "_TtC%zu%s%zu%s", moduleLength, module,
39+
int result = swift_asprintf(&value, "_TtC%zu%s%zu%s", moduleLength, module,
6540
classLength, class_);
6641
assert(result > 0);
6742
(void)result;
@@ -76,11 +51,11 @@ _swift_mangleSimpleProtocol(const char *module, const char *protocol) {
7651
size_t protocolLength = strlen(protocol);
7752
char *value = nullptr;
7853
if (swift::STDLIB_NAME == llvm::StringRef(module)) {
79-
int result = asprintf(&value, "_TtPs%zu%s_", protocolLength, protocol);
54+
int result = swift_asprintf(&value, "_TtPs%zu%s_", protocolLength, protocol);
8055
assert(result > 0);
8156
(void)result;
8257
} else {
83-
int result = asprintf(&value, "_TtP%zu%s%zu%s_", moduleLength, module,
58+
int result = swift_asprintf(&value, "_TtP%zu%s%zu%s_", moduleLength, module,
8459
protocolLength, protocol);
8560
assert(result > 0);
8661
(void)result;

stdlib/public/runtime/Errors.cpp

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "ImageInspection.h"
4040
#include "swift/Runtime/Debug.h"
4141
#include "swift/Runtime/Mutex.h"
42+
#include "swift/Runtime/Portability.h"
4243
#include "swift/Demangling/Demangle.h"
4344
#include "llvm/ADT/StringRef.h"
4445

@@ -288,7 +289,7 @@ reportOnCrash(uint32_t flags, const char *message)
288289
char *oldMessage = (char *)CRGetCrashLogMessage();
289290
char *newMessage;
290291
if (oldMessage) {
291-
asprintf(&newMessage, "%s%s", oldMessage, message);
292+
swift_asprintf(&newMessage, "%s%s", oldMessage, message);
292293
if (malloc_size(oldMessage)) free(oldMessage);
293294
} else {
294295
newMessage = strdup(message);
@@ -367,26 +368,6 @@ void swift::swift_reportError(uint32_t flags,
367368
reportOnCrash(flags, message);
368369
}
369370

370-
static int swift_vasprintf(char **strp, const char *fmt, va_list ap) {
371-
#if defined(_WIN32)
372-
int len = _vscprintf(fmt, ap);
373-
if (len < 0)
374-
return -1;
375-
char *buffer = reinterpret_cast<char *>(malloc(len + 1));
376-
if (!buffer)
377-
return -1;
378-
int result = vsprintf(buffer, fmt, ap);
379-
if (result < 0) {
380-
free(buffer);
381-
return -1;
382-
}
383-
*strp = buffer;
384-
return result;
385-
#else
386-
return vasprintf(strp, fmt, ap);
387-
#endif
388-
}
389-
390371
// Report a fatal error to system console, stderr, and crash logs, then abort.
391372
SWIFT_NORETURN void swift::fatalError(uint32_t flags, const char *format, ...) {
392373
va_list args;

stdlib/public/runtime/ReflectionMirror.cpp

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,27 +43,6 @@
4343
#include <stdarg.h>
4444

4545
namespace {
46-
int asprintf(char **strp, const char *fmt, ...) {
47-
va_list argp0, argp1;
48-
49-
va_start(argp0, fmt);
50-
va_copy(argp1, argp0);
51-
52-
int length = _vscprintf(fmt, argp0);
53-
54-
*strp = reinterpret_cast<char *>(malloc(length + 1));
55-
if (*strp == nullptr)
56-
return -1;
57-
58-
length = _vsnprintf(*strp, length, fmt, argp1);
59-
(*strp)[length] = '\0';
60-
61-
va_end(argp0);
62-
va_end(argp1);
63-
64-
return length;
65-
}
66-
6746
char *strndup(const char *s, size_t n) {
6847
size_t length = std::min(strlen(s), n);
6948

@@ -289,7 +268,7 @@ struct TupleImpl : ReflectionMirrorImpl {
289268
if (!hasLabel) {
290269
// The name is the stringized element number '.0'.
291270
char *str;
292-
asprintf(&str, ".%" PRIdPTR, i);
271+
swift_asprintf(&str, ".%" PRIdPTR, i);
293272
*outName = str;
294273
}
295274

stdlib/public/runtime/SwiftObject.mm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1553,13 +1553,13 @@ void swift_objc_swift3ImplicitObjCEntrypoint(id self, SEL selector,
15531553
filenameLength = INT_MAX;
15541554

15551555
char *message, *nullTerminatedFilename;
1556-
asprintf(&message,
1556+
swift_asprintf(&message,
15571557
"implicit Objective-C entrypoint %c[%s %s] is deprecated and will "
15581558
"be removed in Swift 4",
15591559
isInstanceMethod ? '-' : '+',
15601560
class_getName([self class]),
15611561
sel_getName(selector));
1562-
asprintf(&nullTerminatedFilename, "%*s", (int)filenameLength, filename);
1562+
swift_asprintf(&nullTerminatedFilename, "%*s", (int)filenameLength, filename);
15631563

15641564
RuntimeErrorDetails::FixIt fixit = {
15651565
.filename = nullTerminatedFilename,

stdlib/public/stubs/OptionalBridgingHelper.mm

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "swift/Runtime/Metadata.h"
1818
#include "swift/Runtime/Mutex.h"
1919
#include "swift/Runtime/ObjCBridge.h"
20+
#include "swift/Runtime/Portability.h"
2021
#include <vector>
2122
#import <Foundation/Foundation.h>
2223
#import <CoreFoundation/CoreFoundation.h>
@@ -39,13 +40,10 @@ @interface __SwiftNull : NSObject {
3940

4041
@implementation __SwiftNull : NSObject
4142

42-
// int
43-
// asprintf(char **ret, const char *format, ...);
44-
4543
- (id)description {
4644
char *str = NULL;
4745
const char *clsName = class_getName([self class]);
48-
int fmtResult = asprintf(&str, "<%s %p depth = %u>", clsName,
46+
int fmtResult = swift_asprintf(&str, "<%s %p depth = %u>", clsName,
4947
(void*)self,
5048
self->depth);
5149
(void)fmtResult;

0 commit comments

Comments
 (0)