Skip to content

Commit 0c707c9

Browse files
authored
[libc] Add printf error handling (#162876)
[#159474](#159474) - All printf variants set errno and consistently return -1 on error, instead of returning various predefined error codes - Return value overflow handling is added
1 parent 3a0c534 commit 0c707c9

39 files changed

+584
-104
lines changed

libc/src/stdio/CMakeLists.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ add_entrypoint_object(
125125
DEPENDS
126126
libc.src.stdio.printf_core.printf_main
127127
libc.src.stdio.printf_core.writer
128+
libc.src.stdio.printf_core.core_structs
129+
libc.src.stdio.printf_core.error_mapper
130+
libc.src.__support.libc_errno
131+
libc.src.__support.CPP.limits
128132
)
129133

130134
add_entrypoint_object(
@@ -136,6 +140,10 @@ add_entrypoint_object(
136140
DEPENDS
137141
libc.src.stdio.printf_core.printf_main
138142
libc.src.stdio.printf_core.writer
143+
libc.src.stdio.printf_core.core_structs
144+
libc.src.stdio.printf_core.error_mapper
145+
libc.src.__support.libc_errno
146+
libc.src.__support.CPP.limits
139147
)
140148

141149
add_entrypoint_object(
@@ -146,6 +154,10 @@ add_entrypoint_object(
146154
asprintf.h
147155
DEPENDS
148156
libc.src.stdio.printf_core.vasprintf_internal
157+
libc.src.stdio.printf_core.core_structs
158+
libc.src.stdio.printf_core.error_mapper
159+
libc.src.__support.libc_errno
160+
libc.src.__support.CPP.limits
149161
)
150162

151163
add_entrypoint_object(
@@ -157,6 +169,10 @@ add_entrypoint_object(
157169
DEPENDS
158170
libc.src.stdio.printf_core.printf_main
159171
libc.src.stdio.printf_core.writer
172+
libc.src.stdio.printf_core.core_structs
173+
libc.src.stdio.printf_core.error_mapper
174+
libc.src.__support.libc_errno
175+
libc.src.__support.CPP.limits
160176
)
161177

162178
add_entrypoint_object(
@@ -168,6 +184,10 @@ add_entrypoint_object(
168184
DEPENDS
169185
libc.src.stdio.printf_core.printf_main
170186
libc.src.stdio.printf_core.writer
187+
libc.src.stdio.printf_core.core_structs
188+
libc.src.stdio.printf_core.error_mapper
189+
libc.src.__support.libc_errno
190+
libc.src.__support.CPP.limits
171191
)
172192

173193
add_entrypoint_object(
@@ -178,6 +198,10 @@ add_entrypoint_object(
178198
vasprintf.h
179199
DEPENDS
180200
libc.src.stdio.printf_core.vasprintf_internal
201+
libc.src.stdio.printf_core.core_structs
202+
libc.src.stdio.printf_core.error_mapper
203+
libc.src.__support.libc_errno
204+
libc.src.__support.CPP.limits
181205
)
182206

183207
add_subdirectory(printf_core)

libc/src/stdio/asprintf.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "src/stdio/asprintf.h"
10+
#include "src/__support/CPP/limits.h"
1011
#include "src/__support/arg_list.h"
12+
#include "src/__support/libc_errno.h"
1113
#include "src/__support/macros/config.h"
14+
#include "src/stdio/printf_core/core_structs.h"
15+
#include "src/stdio/printf_core/error_mapper.h"
1216
#include "src/stdio/printf_core/vasprintf_internal.h"
1317

1418
namespace LIBC_NAMESPACE_DECL {
@@ -22,8 +26,18 @@ LLVM_LIBC_FUNCTION(int, asprintf,
2226
// and pointer semantics, as well as handling
2327
// destruction automatically.
2428
va_end(vlist);
25-
int ret = printf_core::vasprintf_internal(buffer, format, args);
26-
return ret;
29+
auto ret_val = printf_core::vasprintf_internal(buffer, format, args);
30+
if (!ret_val.has_value()) {
31+
libc_errno = printf_core::internal_error_to_errno(ret_val.error());
32+
return -1;
33+
}
34+
if (ret_val.value() > cpp::numeric_limits<int>::max()) {
35+
libc_errno =
36+
printf_core::internal_error_to_errno(-printf_core::OVERFLOW_ERROR);
37+
return -1;
38+
}
39+
40+
return static_cast<int>(ret_val.value());
2741
}
2842

2943
} // namespace LIBC_NAMESPACE_DECL

libc/src/stdio/baremetal/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,12 @@ add_entrypoint_object(
2929
DEPENDS
3030
libc.src.stdio.printf_core.printf_main
3131
libc.src.stdio.printf_core.writer
32+
libc.src.stdio.printf_core.error_mapper
33+
libc.src.stdio.printf_core.core_structs
3234
libc.src.__support.arg_list
3335
libc.src.__support.OSUtil.osutil
36+
libc.src.__support.libc_errno
37+
libc.src.__support.CPP.limits
3438
)
3539

3640
add_entrypoint_object(
@@ -87,8 +91,12 @@ add_entrypoint_object(
8791
DEPENDS
8892
libc.src.stdio.printf_core.printf_main
8993
libc.src.stdio.printf_core.writer
94+
libc.src.stdio.printf_core.error_mapper
95+
libc.src.stdio.printf_core.core_structs
9096
libc.src.__support.arg_list
9197
libc.src.__support.OSUtil.osutil
98+
libc.src.__support.libc_errno
99+
libc.src.__support.CPP.limits
92100
)
93101

94102
add_entrypoint_object(

libc/src/stdio/baremetal/printf.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "src/stdio/printf.h"
10+
#include "src/__support/CPP/limits.h"
1011
#include "src/__support/OSUtil/io.h"
1112
#include "src/__support/arg_list.h"
13+
#include "src/__support/libc_errno.h"
1214
#include "src/__support/macros/config.h"
1315
#include "src/stdio/printf_core/core_structs.h"
16+
#include "src/stdio/printf_core/error_mapper.h"
1417
#include "src/stdio/printf_core/printf_main.h"
1518
#include "src/stdio/printf_core/writer.h"
1619

@@ -42,13 +45,25 @@ LLVM_LIBC_FUNCTION(int, printf, (const char *__restrict format, ...)) {
4245
buffer, BUFF_SIZE, &stdout_write_hook, nullptr);
4346
printf_core::Writer<printf_core::WriteMode::FLUSH_TO_STREAM> writer(wb);
4447

45-
int retval = printf_core::printf_main(&writer, format, args);
48+
auto retval = printf_core::printf_main(&writer, format, args);
49+
if (!retval.has_value()) {
50+
libc_errno = printf_core::internal_error_to_errno(retval.error());
51+
return -1;
52+
}
4653

4754
int flushval = wb.overflow_write("");
48-
if (flushval != printf_core::WRITE_OK)
49-
retval = flushval;
55+
if (flushval != printf_core::WRITE_OK) {
56+
libc_errno = printf_core::internal_error_to_errno(-flushval);
57+
return -1;
58+
}
5059

51-
return retval;
60+
if (retval.value() > cpp::numeric_limits<int>::max()) {
61+
libc_errno =
62+
printf_core::internal_error_to_errno(-printf_core::OVERFLOW_ERROR);
63+
return -1;
64+
}
65+
66+
return static_cast<int>(retval.value());
5267
}
5368

5469
} // namespace LIBC_NAMESPACE_DECL

libc/src/stdio/baremetal/vprintf.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "src/stdio/vprintf.h"
10+
#include "src/__support/CPP/limits.h"
1011
#include "src/__support/OSUtil/io.h"
1112
#include "src/__support/arg_list.h"
13+
#include "src/__support/libc_errno.h"
1214
#include "src/__support/macros/config.h"
1315
#include "src/stdio/printf_core/core_structs.h"
16+
#include "src/stdio/printf_core/error_mapper.h"
1417
#include "src/stdio/printf_core/printf_main.h"
1518
#include "src/stdio/printf_core/writer.h"
1619

@@ -40,13 +43,25 @@ LLVM_LIBC_FUNCTION(int, vprintf,
4043
buffer, BUFF_SIZE, &stdout_write_hook, nullptr);
4144
printf_core::Writer<printf_core::WriteMode::FLUSH_TO_STREAM> writer(wb);
4245

43-
int retval = printf_core::printf_main(&writer, format, args);
46+
auto retval = printf_core::printf_main(&writer, format, args);
47+
if (!retval.has_value()) {
48+
libc_errno = printf_core::internal_error_to_errno(retval.error());
49+
return -1;
50+
}
4451

4552
int flushval = wb.overflow_write("");
46-
if (flushval != printf_core::WRITE_OK)
47-
retval = flushval;
53+
if (flushval != printf_core::WRITE_OK) {
54+
libc_errno = printf_core::internal_error_to_errno(-flushval);
55+
return -1;
56+
}
4857

49-
return retval;
58+
if (retval.value() > cpp::numeric_limits<int>::max()) {
59+
libc_errno =
60+
printf_core::internal_error_to_errno(-printf_core::OVERFLOW_ERROR);
61+
return -1;
62+
}
63+
64+
return static_cast<int>(retval.value());
5065
}
5166

5267
} // namespace LIBC_NAMESPACE_DECL

libc/src/stdio/generic/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,11 @@ add_generic_entrypoint_object(
393393
list(APPEND fprintf_deps
394394
libc.hdr.types.FILE
395395
libc.src.__support.arg_list
396+
libc.src.__support.CPP.limits
397+
libc.src.__support.libc_errno
396398
libc.src.stdio.printf_core.vfprintf_internal
399+
libc.src.stdio.printf_core.core_structs
400+
libc.src.stdio.printf_core.error_mapper
397401
)
398402

399403
if(LLVM_LIBC_FULL_BUILD)

libc/src/stdio/generic/fprintf.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88

99
#include "src/stdio/fprintf.h"
1010

11+
#include "src/__support/CPP/limits.h"
1112
#include "src/__support/File/file.h"
1213
#include "src/__support/arg_list.h"
1314
#include "src/__support/macros/config.h"
15+
#include "src/stdio/printf_core/core_structs.h"
16+
#include "src/stdio/printf_core/error_mapper.h"
1417
#include "src/stdio/printf_core/vfprintf_internal.h"
1518

1619
#include "hdr/types/FILE.h"
@@ -27,8 +30,18 @@ LLVM_LIBC_FUNCTION(int, fprintf,
2730
// and pointer semantics, as well as handling
2831
// destruction automatically.
2932
va_end(vlist);
30-
int ret_val = printf_core::vfprintf_internal(stream, format, args);
31-
return ret_val;
33+
auto ret_val = printf_core::vfprintf_internal(stream, format, args);
34+
if (!ret_val.has_value()) {
35+
libc_errno = printf_core::internal_error_to_errno(ret_val.error());
36+
return -1;
37+
}
38+
if (ret_val.value() > cpp::numeric_limits<int>::max()) {
39+
libc_errno =
40+
printf_core::internal_error_to_errno(-printf_core::OVERFLOW_ERROR);
41+
return -1;
42+
}
43+
44+
return static_cast<int>(ret_val.value());
3245
}
3346

3447
} // namespace LIBC_NAMESPACE_DECL

libc/src/stdio/generic/printf.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88

99
#include "src/stdio/printf.h"
1010

11+
#include "src/__support/CPP/limits.h"
1112
#include "src/__support/File/file.h"
1213
#include "src/__support/arg_list.h"
1314
#include "src/__support/macros/config.h"
15+
#include "src/stdio/printf_core/core_structs.h"
16+
#include "src/stdio/printf_core/error_mapper.h"
1417
#include "src/stdio/printf_core/vfprintf_internal.h"
1518

1619
#include "hdr/types/FILE.h"
@@ -31,9 +34,19 @@ LLVM_LIBC_FUNCTION(int, printf, (const char *__restrict format, ...)) {
3134
// and pointer semantics, as well as handling
3235
// destruction automatically.
3336
va_end(vlist);
34-
int ret_val = printf_core::vfprintf_internal(
37+
auto ret_val = printf_core::vfprintf_internal(
3538
reinterpret_cast<::FILE *>(PRINTF_STDOUT), format, args);
36-
return ret_val;
39+
if (!ret_val.has_value()) {
40+
libc_errno = printf_core::internal_error_to_errno(ret_val.error());
41+
return -1;
42+
}
43+
if (ret_val.value() > cpp::numeric_limits<int>::max()) {
44+
libc_errno =
45+
printf_core::internal_error_to_errno(-printf_core::OVERFLOW_ERROR);
46+
return -1;
47+
}
48+
49+
return static_cast<int>(ret_val.value());
3750
}
3851

3952
} // namespace LIBC_NAMESPACE_DECL

libc/src/stdio/generic/vfprintf.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88

99
#include "src/stdio/vfprintf.h"
1010

11+
#include "src/__support/CPP/limits.h"
1112
#include "src/__support/File/file.h"
1213
#include "src/__support/arg_list.h"
1314
#include "src/__support/macros/config.h"
15+
#include "src/stdio/printf_core/core_structs.h"
16+
#include "src/stdio/printf_core/error_mapper.h"
1417
#include "src/stdio/printf_core/vfprintf_internal.h"
1518

1619
#include "hdr/types/FILE.h"
@@ -24,8 +27,18 @@ LLVM_LIBC_FUNCTION(int, vfprintf,
2427
internal::ArgList args(vlist); // This holder class allows for easier copying
2528
// and pointer semantics, as well as handling
2629
// destruction automatically.
27-
int ret_val = printf_core::vfprintf_internal(stream, format, args);
28-
return ret_val;
30+
auto ret_val = printf_core::vfprintf_internal(stream, format, args);
31+
if (!ret_val.has_value()) {
32+
libc_errno = printf_core::internal_error_to_errno(ret_val.error());
33+
return -1;
34+
}
35+
if (ret_val.value() > cpp::numeric_limits<int>::max()) {
36+
libc_errno =
37+
printf_core::internal_error_to_errno(-printf_core::OVERFLOW_ERROR);
38+
return -1;
39+
}
40+
41+
return static_cast<int>(ret_val.value());
2942
}
3043

3144
} // namespace LIBC_NAMESPACE_DECL

libc/src/stdio/generic/vprintf.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88

99
#include "src/stdio/vprintf.h"
1010

11+
#include "src/__support/CPP/limits.h"
1112
#include "src/__support/File/file.h"
1213
#include "src/__support/arg_list.h"
1314
#include "src/__support/macros/config.h"
15+
#include "src/stdio/printf_core/core_structs.h"
16+
#include "src/stdio/printf_core/error_mapper.h"
1417
#include "src/stdio/printf_core/vfprintf_internal.h"
1518

1619
#include "hdr/types/FILE.h"
@@ -29,9 +32,19 @@ LLVM_LIBC_FUNCTION(int, vprintf,
2932
internal::ArgList args(vlist); // This holder class allows for easier copying
3033
// and pointer semantics, as well as handling
3134
// destruction automatically.
32-
int ret_val = printf_core::vfprintf_internal(
35+
auto ret_val = printf_core::vfprintf_internal(
3336
reinterpret_cast<::FILE *>(PRINTF_STDOUT), format, args);
34-
return ret_val;
37+
if (!ret_val.has_value()) {
38+
libc_errno = printf_core::internal_error_to_errno(ret_val.error());
39+
return -1;
40+
}
41+
if (ret_val.value() > cpp::numeric_limits<int>::max()) {
42+
libc_errno =
43+
printf_core::internal_error_to_errno(-printf_core::OVERFLOW_ERROR);
44+
return -1;
45+
}
46+
47+
return static_cast<int>(ret_val.value());
3548
}
3649

3750
} // namespace LIBC_NAMESPACE_DECL

0 commit comments

Comments
 (0)