mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-01 09:41:08 +00:00
[libc] add integer writing to printf
This patch adds %n to printf, as well as a compiler flag to disable it. This is due to it having serious security issues when misused. Reviewed By: lntue Differential Revision: https://reviews.llvm.org/D127517
This commit is contained in:
parent
f239cddbac
commit
88b801392c
@ -64,6 +64,7 @@ add_object_library(
|
||||
hex_converter.h
|
||||
ptr_converter.h
|
||||
oct_converter.h
|
||||
write_int_converter.h
|
||||
DEPENDS
|
||||
.writer
|
||||
.core_structs
|
||||
|
@ -57,9 +57,10 @@ int convert(Writer *writer, const FormatSection &to_conv) {
|
||||
case 'g':
|
||||
case 'G':
|
||||
// return convert_float_mixed(writer, to_conv);
|
||||
// TODO(michaelrj): add a flag to disable writing an int here
|
||||
#ifndef LLVM_LIBC_PRINTF_DISABLE_WRITE_INT
|
||||
case 'n':
|
||||
// return convert_write_int(writer, to_conv);
|
||||
return convert_write_int(writer, to_conv);
|
||||
#endif // LLVM_LIBC_PRINTF_DISABLE_WRITE_INT
|
||||
case 'p':
|
||||
return convert_pointer(writer, to_conv);
|
||||
default:
|
||||
|
@ -33,8 +33,9 @@
|
||||
// defines convert_float_hex_exp
|
||||
// defines convert_float_mixed
|
||||
|
||||
// TODO(michaelrj): add a flag to disable writing an int here
|
||||
// defines convert_write_int
|
||||
#ifndef LLVM_LIBC_PRINTF_DISABLE_WRITE_INT
|
||||
#include "src/stdio/printf_core/write_int_converter.h"
|
||||
#endif // LLVM_LIBC_PRINTF_DISABLE_WRITE_INT
|
||||
|
||||
// defines convert_pointer
|
||||
#include "src/stdio/printf_core/ptr_converter.h"
|
||||
|
@ -137,7 +137,9 @@ FormatSection Parser::get_next_section() {
|
||||
section.conv_val_raw = bit_cast<fputil::FPBits<long double>::UIntType>(
|
||||
GET_ARG_VAL_SIMPLEST(long double, conv_index));
|
||||
break;
|
||||
#ifndef LLVM_LIBC_PRINTF_DISABLE_WRITE_INT
|
||||
case ('n'):
|
||||
#endif // LLVM_LIBC_PRINTF_DISABLE_WRITE_INT
|
||||
case ('p'):
|
||||
case ('s'):
|
||||
section.conv_val_ptr = GET_ARG_VAL_SIMPLEST(void *, conv_index);
|
||||
@ -351,7 +353,9 @@ Parser::TypeDesc Parser::get_type_desc(size_t index) {
|
||||
else
|
||||
conv_size = TYPE_DESC<long double>;
|
||||
break;
|
||||
#ifndef LLVM_LIBC_PRINTF_DISABLE_WRITE_INT
|
||||
case ('n'):
|
||||
#endif // LLVM_LIBC_PRINTF_DISABLE_WRITE_INT
|
||||
case ('p'):
|
||||
case ('s'):
|
||||
conv_size = TYPE_DESC<void *>;
|
||||
|
65
libc/src/stdio/printf_core/write_int_converter.h
Normal file
65
libc/src/stdio/printf_core/write_int_converter.h
Normal file
@ -0,0 +1,65 @@
|
||||
//===-- Write integer Converter for printf ----------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_WRITE_INT_CONVERTER_H
|
||||
#define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_WRITE_INT_CONVERTER_H
|
||||
|
||||
#include "src/__support/CPP/Limits.h"
|
||||
#include "src/stdio/printf_core/core_structs.h"
|
||||
#include "src/stdio/printf_core/writer.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
namespace printf_core {
|
||||
|
||||
int inline convert_write_int(Writer *writer, const FormatSection &to_conv) {
|
||||
|
||||
// This is an additional check added by LLVM-libc. The reason it returns -3 is
|
||||
// because printf uses negative return values for errors, and -1 and -2 are
|
||||
// already in use by the file_writer class for file errors.
|
||||
if (to_conv.conv_val_ptr == nullptr)
|
||||
return -3;
|
||||
|
||||
int written = writer->get_chars_written();
|
||||
|
||||
switch (to_conv.length_modifier) {
|
||||
case LengthModifier::none:
|
||||
*reinterpret_cast<int *>(to_conv.conv_val_ptr) = written;
|
||||
break;
|
||||
case LengthModifier::l:
|
||||
*reinterpret_cast<long *>(to_conv.conv_val_ptr) = written;
|
||||
break;
|
||||
case LengthModifier::ll:
|
||||
case LengthModifier::L:
|
||||
*reinterpret_cast<long long *>(to_conv.conv_val_ptr) = written;
|
||||
break;
|
||||
case LengthModifier::h:
|
||||
*reinterpret_cast<short *>(to_conv.conv_val_ptr) = written;
|
||||
break;
|
||||
case LengthModifier::hh:
|
||||
*reinterpret_cast<signed char *>(to_conv.conv_val_ptr) = written;
|
||||
break;
|
||||
case LengthModifier::z:
|
||||
*reinterpret_cast<size_t *>(to_conv.conv_val_ptr) = written;
|
||||
break;
|
||||
case LengthModifier::t:
|
||||
*reinterpret_cast<ptrdiff_t *>(to_conv.conv_val_ptr) = written;
|
||||
break;
|
||||
case LengthModifier::j:
|
||||
*reinterpret_cast<uintmax_t *>(to_conv.conv_val_ptr) = written;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace printf_core
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_WRITE_INT_CONVERTER_H
|
@ -92,7 +92,7 @@ TEST(LlvmLibcSPrintfTest, IntConv) {
|
||||
|
||||
// Length Modifier Tests.
|
||||
|
||||
written = __llvm_libc::sprintf(buff, "%hhu", 257); // 0x10001
|
||||
written = __llvm_libc::sprintf(buff, "%hhu", 257); // 0x101
|
||||
EXPECT_EQ(written, 1);
|
||||
ASSERT_STREQ(buff, "1");
|
||||
|
||||
@ -483,6 +483,41 @@ TEST(LlvmLibcSPrintfTest, OctConv) {
|
||||
ASSERT_STREQ(buff, "0077 01000000000000 002 ");
|
||||
}
|
||||
|
||||
#ifndef LLVM_LIBC_PRINTF_DISABLE_WRITE_INT
|
||||
TEST(LlvmLibcSPrintfTest, WriteIntConv) {
|
||||
char buff[64];
|
||||
int written;
|
||||
int test_val = -1;
|
||||
|
||||
test_val = -1;
|
||||
written = __llvm_libc::sprintf(buff, "12345%n67890", &test_val);
|
||||
EXPECT_EQ(written, 10);
|
||||
EXPECT_EQ(test_val, 5);
|
||||
ASSERT_STREQ(buff, "1234567890");
|
||||
|
||||
test_val = -1;
|
||||
written = __llvm_libc::sprintf(buff, "%n", &test_val);
|
||||
EXPECT_EQ(written, 0);
|
||||
EXPECT_EQ(test_val, 0);
|
||||
ASSERT_STREQ(buff, "");
|
||||
|
||||
test_val = 0x100;
|
||||
written = __llvm_libc::sprintf(buff, "ABC%hhnDEF", &test_val);
|
||||
EXPECT_EQ(written, 6);
|
||||
EXPECT_EQ(test_val, 0x103);
|
||||
ASSERT_STREQ(buff, "ABCDEF");
|
||||
|
||||
test_val = -1;
|
||||
written = __llvm_libc::sprintf(buff, "%s%n", "87654321", &test_val);
|
||||
EXPECT_EQ(written, 8);
|
||||
EXPECT_EQ(test_val, 8);
|
||||
ASSERT_STREQ(buff, "87654321");
|
||||
|
||||
written = __llvm_libc::sprintf(buff, "abc123%n", nullptr);
|
||||
EXPECT_LT(written, 0);
|
||||
}
|
||||
#endif // LLVM_LIBC_PRINTF_DISABLE_WRITE_INT
|
||||
|
||||
#ifndef LLVM_LIBC_PRINTF_DISABLE_INDEX_MODE
|
||||
TEST(LlvmLibcSPrintfTest, IndexModeParsing) {
|
||||
char buff[64];
|
||||
|
Loading…
Reference in New Issue
Block a user