#include "src/__support/common.h"
#include <stdarg.h>
+#include <stddef.h>
namespace __llvm_libc {
namespace internal {
template <class T> LIBC_INLINE T next_var() { return va_arg(vlist, T); }
};
+// Used for testing things that use an ArgList when it's impossible to know what
+// the arguments should be ahead of time. An example of this would be fuzzing,
+// since a function passed a random input could request unpredictable arguments.
+class MockArgList {
+ size_t arg_counter = 0;
+
+public:
+ LIBC_INLINE MockArgList() = default;
+ LIBC_INLINE MockArgList(va_list) { ; }
+ LIBC_INLINE MockArgList(MockArgList &other) {
+ arg_counter = other.arg_counter;
+ }
+ LIBC_INLINE ~MockArgList() = default;
+
+ LIBC_INLINE MockArgList &operator=(MockArgList &rhs) {
+ arg_counter = rhs.arg_counter;
+ return *this;
+ }
+
+ template <class T> LIBC_INLINE T next_var() {
+ ++arg_counter;
+ return T(arg_counter);
+ }
+
+ size_t read_count() const { return arg_counter; }
+};
+
} // namespace internal
} // namespace __llvm_libc
namespace __llvm_libc {
namespace printf_core {
+#ifndef LIBC_COPT_MOCK_ARG_LIST
+using ArgProvider = internal::ArgList;
+#else // not defined LIBC_COPT_MOCK_ARG_LIST
+using ArgProvider = internal::MockArgList;
+#endif // LIBC_COPT_MOCK_ARG_LIST
+
class Parser {
const char *__restrict str;
size_t cur_pos = 0;
- internal::ArgList args_cur;
+ ArgProvider args_cur;
#ifndef LIBC_COPT_PRINTF_DISABLE_INDEX_MODE
// args_start stores the start of the va_args, which is allows getting the
// value of arguments that have already been passed. args_index is tracked so
// that we know which argument args_cur is on.
- internal::ArgList args_start;
+ ArgProvider args_start;
size_t args_index = 1;
// Defined in printf_config.h
static constexpr size_t DESC_ARR_LEN = LIBC_COPT_PRINTF_INDEX_ARR_LEN;
- // desc_arr stores the sizes of the variables in the ArgList. This is used in
- // index mode to reduce repeated string parsing. The sizes are stored as
+ // desc_arr stores the sizes of the variables in the ArgProvider. This is used
+ // in index mode to reduce repeated string parsing. The sizes are stored as
// TypeDesc objects, which store the size as well as minimal type information.
// This is necessary because some systems separate the floating point and
// integer values in va_args.
public:
#ifndef LIBC_COPT_PRINTF_DISABLE_INDEX_MODE
- LIBC_INLINE Parser(const char *__restrict new_str, internal::ArgList &args)
+ LIBC_INLINE Parser(const char *__restrict new_str, ArgProvider &args)
: str(new_str), args_cur(args), args_start(args) {}
#else
- LIBC_INLINE Parser(const char *__restrict new_str, internal::ArgList &args)
+ LIBC_INLINE Parser(const char *__restrict new_str, ArgProvider &args)
: str(new_str), args_cur(args) {}
#endif // LIBC_COPT_PRINTF_DISABLE_INDEX_MODE
return get_next_arg_value<T>();
}
- // the ArgList can only return the next item in the list. This function is
+ // the ArgProvider can only return the next item in the list. This function is
// used in index mode when the item that needs to be read is not the next one.
// It moves cur_args to the index requested so the the appropriate value may
// be read. This may involve parsing the format string, and is in the worst