// Copyright 2022 The Centipede Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef THIRD_PARTY_CENTIPEDE_GOOGLE_CONFIG_FILE_H_ #define THIRD_PARTY_CENTIPEDE_GOOGLE_CONFIG_FILE_H_ #include // NOLINT #include #include #include #include #include #include "absl/base/nullability.h" #include "./centipede/config_init.h" // TODO(ussuri): Move implementation-only functions to .cc. namespace fuzztest::internal { // Constructs an augmented copy of `argv` with any substrings appearing in the // original elements replaced according to a list replacements. // TODO(ussuri): Make more robust. What we really want is replace any possible // form of --flag=value with an equivalent form of --new_flag=new_value. // TODO(ussuri): Remove and just use the required bits of logic in .cc. class AugmentedArgvWithCleanup final { public: using Replacements = std::vector>; using BackingResourcesCleanup = std::function; // Ctor. The `orig_argc` and `orig_argv` are compatible with those passed to a // main(). Each item in `orig_argv` is first processed with // `flag_replacements` if the item has the format "-flag", "-flag=...", // "--flag", or "--flag=", and the flag name matches. Then the `replacements` // map should map an old substring to a new one. Only simple, one-stage string // replacement is performed: no regexes, placeholders, envvars or recursion. // The `cleanup` callback should clean up any temporary resources backing the // modified flags, such as temporary files. AugmentedArgvWithCleanup(const std::vector& orig_argv, const Replacements& flag_replacements, const Replacements& replacements, BackingResourcesCleanup&& cleanup); // Dtor. Invokes `cleanup_`. ~AugmentedArgvWithCleanup(); // Movable by not copyable to prevent `cleanup_` from running twice. AugmentedArgvWithCleanup(const AugmentedArgvWithCleanup&) = delete; AugmentedArgvWithCleanup& operator=(const AugmentedArgvWithCleanup&) = delete; AugmentedArgvWithCleanup(AugmentedArgvWithCleanup&&) noexcept; AugmentedArgvWithCleanup& operator=(AugmentedArgvWithCleanup&&) noexcept; // The new argc. Currently, will always match the original argc. int argc() const { return static_cast(argv_.size()); } // The new, possibly augmented argv. Note that all its char* elements are // backed by newly allocated std::strings, so they will all be different from // their counterparts in the original argv. const std::vector& argv() const { return argv_; } // Whether the original argv has been augmented from the original, i.e. if any // of the requested string replacements actually occurred. bool was_augmented() const { return was_augmented_; } private: std::vector argv_; bool was_augmented_; BackingResourcesCleanup cleanup_; }; // Replaces any --config= in `argv` (or any alternative form of // that flag) with a --flagfile=, where // localization means that a remote is copied to a temporary local // mirror. If is already local, it is used as-is. // // The remote file contents is additionally checked for possible nested // --config, --save_config and --flagfile: such usage is currently unsupported. // // The returned AugmentedArgvWithCleanup deletes the localized files (if any) in // dtor. AugmentedArgvWithCleanup LocalizeConfigFilesInArgv( const std::vector& argv); // If --save_config= was passed on the command line, saves _all_ // Centipede flags (i.e. those specified on the command line AND the defaulted // ones) to in the format compatible with --config (defined by // Centipede), as well as --flagfile (defined by Abseil Flags), and returns // . Otherwise, returns an empty string. If the 's extension is .sh, // saves a runnable script instead. std::filesystem::path MaybeSaveConfigToFile( const std::vector& leftover_argv); // Initializes Centipede: // - Calls `InitRuntime()` at the right time to initialize the runtime // subsystems and perform the initial flag parsing. // - Handles config-related flags: loads the config from --config, if any, // and saves it to --save_config (or --update_config), if any. // - Logs the final resolved config. // - Returns the runtime state that the caller should take ownership of and // keep alive the duration of the process. [[nodiscard]] std::unique_ptr InitCentipede( int argc, char** absl_nonnull argv); } // namespace fuzztest::internal #endif // THIRD_PARTY_CENTIPEDE_GOOGLE_CONFIG_FILE_H_