diff --git a/projects/userver/CMakeLists.txt b/projects/userver/CMakeLists.txt new file mode 100644 index 000000000000..1e8e5cd5b9d5 --- /dev/null +++ b/projects/userver/CMakeLists.txt @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 3.12...3.31) +project(fuzzservice CXX) + +# Static linking configuration - only when not fuzzing +if(NOT DEFINED ENV{LIB_FUZZING_ENGINE}) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") + set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") + set(BUILD_SHARED_LIBS OFF) +endif() + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +include(DownloadUserver) + +find_package(userver COMPONENTS + core + QUIET +) +if(NOT userver_FOUND) + # Tries TRY_DIR first, falls back to downloading userver from GitHub using CPM. + download_userver(TRY_DIR third_party/userver) +endif() + +userver_setup_environment() + + +# Common sources +include_directories(src) + +add_library(${PROJECT_NAME}_objs OBJECT + src/greeting.cpp + src/hello.cpp +) +target_link_libraries(${PROJECT_NAME}_objs PUBLIC + userver::core +) + +# The Service +add_executable(${PROJECT_NAME} src/main.cpp) +userver_embed_file(${PROJECT_NAME}_config NAME static_config_yaml FILEPATH static_config.yaml) + +if(DEFINED ENV{LIB_FUZZING_ENGINE}) + message("LIB_FUZZING_ENGINE set - $ENV{LIB_FUZZING_ENGINE}") + target_link_libraries(${PROJECT_NAME} PRIVATE + ${PROJECT_NAME}_objs + $ENV{LIB_FUZZING_ENGINE} + ${PROJECT_NAME}_config) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} $ENV{LIB_FUZZING_ENGINE} $ENV{LIB_HFND}") + add_definitions(-DLIB_FUZZING_ENGINE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") +else() + target_link_libraries(${PROJECT_NAME} PRIVATE ${PROJECT_NAME}_objs ${PROJECT_NAME}_config) +endif() diff --git a/projects/userver/CMakePresets.json b/projects/userver/CMakePresets.json new file mode 100644 index 000000000000..0b8a3fe92e02 --- /dev/null +++ b/projects/userver/CMakePresets.json @@ -0,0 +1,46 @@ +{ + "version": 2, + "cmakeMinimumRequired": { + "major": 3, + "minor": 20, + "patch": 0 + }, + "configurePresets": [ + { + "name": "debug", + "displayName": "Debug", + "description": "Fully featured Debug build", + "inherits": [ + "common-flags" + ], + "binaryDir": "${sourceDir}/build-debug", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_CXX_FLAGS": "", + "CMAKE_EXE_LINKER_FLAGS": "-pthread -ldl -lrt -rpath '$ORIGIN/lib'", + "USERVER_SANITIZE_old": "addr;ub", + "USERVER_SANITIZE": "addr" + } + }, + { + "name": "release", + "displayName": "Release", + "description": "Fully featured Release build", + "inherits": [ + "common-flags" + ], + "binaryDir": "${sourceDir}/build-release", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "common-flags", + "hidden": true, + "generator": "Ninja", + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + } + } + ] +} \ No newline at end of file diff --git a/projects/userver/Dockerfile b/projects/userver/Dockerfile new file mode 100644 index 000000000000..e6f926f47365 --- /dev/null +++ b/projects/userver/Dockerfile @@ -0,0 +1,23 @@ +FROM gcr.io/oss-fuzz-base/base-builder +RUN apt-get update && apt-get install -y make autoconf automake libtool ninja-build libyaml-cpp-dev libzstd-dev libre2-dev libicu-dev zlib1g-dev libnghttp2-dev libev-dev clang-format +RUN apt-get install -y ccache cmake git libbenchmark-dev libbson-dev libcctz-dev libcurl4-openssl-dev libev-dev libgmock-dev libc-ares-dev libfmt-dev libgrpc-dev libgrpc++-dev libgrpc++1 libgtest-dev libhiredis-dev libjemalloc-dev libkrb5-dev libldap2-dev libmongoc-dev libnghttp2-dev libpq-dev libprotoc-dev libssl-dev libyaml-cpp-dev ninja-build pkg-config protobuf-compiler-grpc python3-dev python3-jinja2 python3-pip python3-protobuf python3-venv python3-voluptuous zlib1g-dev chrpath libstdc++-10-dev + +#Ubuntu 20.04 contains only boost 1.74.0 +RUN wget https://archives.boost.io/release/1.81.0/source/boost_1_81_0.tar.gz && \ + tar xzf boost_1_81_0.tar.gz && \ + cd boost_1_81_0 && \ + CXXFLAGS="" LDFLAGS="" ./bootstrap.sh --with-toolset=clang && \ + ./b2 -j$(nproc) link=static install +RUN git clone --depth 1 https://github.com/userver-framework/userver userver + +RUN python3 userver/scripts/userver-create-service fuzzservice + +RUN apt remove -y clang-format +RUN apt install -y clang-format-18 +RUN ln -s /usr/bin/clang-format-18 /usr/bin/clang-format + +COPY build.sh $SRC/ +COPY main.cpp $SRC/ +COPY CMakeLists.txt $SRC/ +COPY CMakePresets.json $SRC/fuzzservice/ +COPY static_config.yaml $SRC/fuzzservice/ diff --git a/projects/userver/build.sh b/projects/userver/build.sh new file mode 100755 index 000000000000..a474c51fceba --- /dev/null +++ b/projects/userver/build.sh @@ -0,0 +1,46 @@ +#!/bin/bash -eu +# Copyright 2025 Google LLC +# +# 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 +# +# http://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. +# +################################################################################ + + +cp fuzzservice/CMakePresets.json fuzzservice/CMakePresets_user.json +jq '.configurePresets[0].cacheVariables += {"USERVER_FEATURE_STACKTRACE":"OFF", "USERVER_FEATURE_STACK_USAGE_MONITOR":"OFF"}' fuzzservice/CMakePresets_user.json > fuzzservice/CMakePresets.json + +# unset CXXFLAGS +# unset LDFLAGS + +printenv + +if [[ "$FUZZING_ENGINE" == "honggfuzz" ]] +then + # cp $SRC/CMakeLists.txt $SRC/fuzzservice/CMakeLists.txt + cp $SRC/main.cpp $SRC/fuzzservice/src/main.cpp +fi + +cp $SRC/CMakeLists.txt $SRC/fuzzservice/CMakeLists.txt + +cd fuzzservice +make build-debug + +cp build-debug/fuzzservice $OUT/ + +mkdir -p $OUT/lib/ +cp /usr/lib/x86_64-linux-gnu/libcctz.so.2 $OUT/lib/ +cp /usr/lib/x86_64-linux-gnu/libicudata.so.66 $OUT/lib/ +cp /usr/lib/x86_64-linux-gnu/libicui18n.so.66 $OUT/lib/ +cp /usr/lib/x86_64-linux-gnu/libicuuc.so.66 $OUT/lib/ + +chrpath -r '$ORIGIN/lib' $OUT/fuzzservice \ No newline at end of file diff --git a/projects/userver/main.cpp b/projects/userver/main.cpp new file mode 100644 index 000000000000..7570dc60a502 --- /dev/null +++ b/projects/userver/main.cpp @@ -0,0 +1,51 @@ +// Copyright 2025 Google LLC +// +// 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 +// +// http://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. +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include +#include + +#define HFND_FUZZING_ENTRY_FUNCTION_CXX(x,y) extern const char* LIBHFNETDRIVER_module_netdriver;const char** LIBHFNETDRIVER_tmp1 = &LIBHFNETDRIVER_module_netdriver;extern "C" int HonggfuzzNetDriver_main(x,y);int HonggfuzzNetDriver_main(x,y) + +// Suppress LSAN for rapidjson +extern "C" const char* __lsan_default_suppressions() { + return "leak:userver::v2_::components::DynamicConfig::Impl::ReadFallback\n"; + } + +#ifdef HFND_FUZZING_ENTRY_FUNCTION_CXX +HFND_FUZZING_ENTRY_FUNCTION_CXX(int argc, char* argv[]) { +#else +int main(int argc, char* argv[]) { +#endif + + auto component_list = userver::components::MinimalServerComponentList() + .Append() + .Append(); + auto config = userver::components::InMemoryConfig{userver::utils::FindResource("static_config_yaml")}; + + return userver::utils::DaemonMain(config, component_list); +} + +#ifndef LIB_FUZZING_ENGINE +int main(int argc, char* argv[]) { + return HonggfuzzNetDriver_main(argc, argv); +} +#endif \ No newline at end of file diff --git a/projects/userver/project.yaml b/projects/userver/project.yaml new file mode 100644 index 000000000000..2aab286356e1 --- /dev/null +++ b/projects/userver/project.yaml @@ -0,0 +1,9 @@ +homepage: "https://userver.tech/" +language: c++ +primary_contact: "antoshkka@gmail.com" +main_repo: "https://github.com/userver-framework/userver.git" +file_github_issue: true +auto_ccs: + - "kirikpavlov@gmail.com" +fuzzing_engines: + - honggfuzz diff --git a/projects/userver/static_config.yaml b/projects/userver/static_config.yaml new file mode 100644 index 000000000000..833038de1691 --- /dev/null +++ b/projects/userver/static_config.yaml @@ -0,0 +1,44 @@ +components_manager: + task_processors: # Task processor is an executor for coroutine tasks + + main-task-processor: # Make a task processor for CPU-bound coroutine tasks. + worker_threads: 1 # Process tasks in 4 threads. + + fs-task-processor: # Make a separate task processor for filesystem bound tasks. + worker_threads: 1 + + default_task_processor: main-task-processor + + components: # Configuring components that were registered via component_list + server: + listener: # configuring the main listening socket... + port: 8080 # ...to listen on this port and... + task_processor: main-task-processor # ...process incoming requests on this task processor. + + logging: + fs-task-processor: fs-task-processor + loggers: + default: + file_path: '@stderr' + level: info + overflow_behavior: discard # Drop logs if the system is too busy to write them down. + + # Dynamic config options. Cache is disabled, updates are disabled. + dynamic-config: + # defaults-path: dynamic_config.yaml + # For most of userver dynamic configs, defaults are used, some are overridden here. + # See userver "dynamic config" docs for what configs exist. + defaults: + HTTP_CLIENT_CONNECTION_POOL_SIZE: 1000 + + handler-ping: + path: /ping + method: GET + task_processor: main-task-processor + throttling_enabled: false + url_trailing_slash: strict-match + + handler-hello: # Finally! Our handler. + path: /hello # Registering handler by URL '/hello'. + method: GET,POST # It will only reply to GET (HEAD) and POST requests. + task_processor: main-task-processor # Run it on CPU bound task processor