[libc-commits] [libc] 47fb6d1 - [libc] add mock arg list

Michael Jones via libc-commits libc-commits at lists.llvm.org
Fri Feb 17 11:18:46 PST 2023


Author: Michael Jones
Date: 2023-02-17T11:18:38-08:00
New Revision: 47fb6d1c65ec227bc3728c401a26d26997b8bcb6

URL: https://github.com/llvm/llvm-project/commit/47fb6d1c65ec227bc3728c401a26d26997b8bcb6
DIFF: https://github.com/llvm/llvm-project/commit/47fb6d1c65ec227bc3728c401a26d26997b8bcb6.diff

LOG: [libc] add mock arg list

For testing purposes we need to be able to mock out the ArgList class.
This patch adds a mock version of that class as well as a flag to enable
it.

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D144145

Added: 
    

Modified: 
    libc/src/__support/arg_list.h
    libc/src/stdio/printf_core/parser.h

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/arg_list.h b/libc/src/__support/arg_list.h
index 5e79f513ff3e0..43cf8352f4b46 100644
--- a/libc/src/__support/arg_list.h
+++ b/libc/src/__support/arg_list.h
@@ -12,6 +12,7 @@
 #include "src/__support/common.h"
 
 #include <stdarg.h>
+#include <stddef.h>
 
 namespace __llvm_libc {
 namespace internal {
@@ -32,6 +33,33 @@ class ArgList {
   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
 

diff  --git a/libc/src/stdio/printf_core/parser.h b/libc/src/stdio/printf_core/parser.h
index 8304d63e6de54..3aedbe0fac2be 100644
--- a/libc/src/stdio/printf_core/parser.h
+++ b/libc/src/stdio/printf_core/parser.h
@@ -20,24 +20,30 @@
 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.
@@ -49,10 +55,10 @@ class Parser {
 
 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
 
@@ -111,7 +117,7 @@ class Parser {
     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


        


More information about the libc-commits mailing list