Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Classic Vulnerabilities #56

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ jobs:
shell: bash
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -C ${{ matrix.cmake-build-type }}
run: ctest -C ${{ matrix.cmake-build-type }} -VV
env:
CTEST_OUTPUT_ON_FAILURE: 1

Expand Down
5 changes: 5 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@ if(PNG_FOUND)
list(APPEND EXTRA_LIBS PNG::PNG)
endif()

add_library(lib_common_dehacked ${SOURCE_FILES_WITH_DEH})
target_compile_definitions(lib_common_dehacked PRIVATE ${DOOM_COMPILE_DEFINITIONS})
target_include_directories(lib_common_dehacked PRIVATE ${GAME_INCLUDE_DIRS})
target_link_libraries(lib_common_dehacked ${EXTRA_LIBS} SampleRate::samplerate)

if(WIN32)
add_executable("${PROGRAM_PREFIX}doom" WIN32 ${SOURCE_FILES_WITH_DEH} "${CMAKE_CURRENT_BINARY_DIR}/resource.rc")
else()
Expand Down
3 changes: 3 additions & 0 deletions src/doom/g_game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2369,7 +2369,10 @@ void G_DoPlayDemo() {
}
// [crispy] make non-fatal
else {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
fmt::fprintf(stderr, message, demoversion, G_VanillaVersionCode(), DemoVersionDescription(demoversion));
#pragma GCC diagnostic pop
fmt::fprintf(stderr, "\n");
g_doomstat_globals->demoplayback = true;
G_CheckDemoStatus();
Expand Down
2 changes: 1 addition & 1 deletion src/i_sdlsound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ static bool ExpandSoundData_SRC(sfxinfo_t * sfxinfo,
}

if (clipped > 0) {
fmt::fprintf(stderr, "Sound '%s': clipped %u samples (%0.2f %%)\n", sfxinfo->name, clipped, 400.0 * clipped / chunk->alen);
fmt::fprintf(stderr, "Sound '%s': clipped %u samples (%0.2f %%)\n", sfxinfo->name.c_str(), clipped, 400.0 * clipped / chunk->alen);
}

return true;
Expand Down
2 changes: 1 addition & 1 deletion src/i_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ uint8_t * I_ZoneBase(int * size) {
i *= 2;

fmt::printf("zone memory: %p, %d MiB allocated for zone\n",
zonemem,
reinterpret_cast<void*>(zonemem),
*size >> 20); // [crispy] human-understandable zone heap size

return zonemem;
Expand Down
10 changes: 2 additions & 8 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
find_package(Catch2 REQUIRED)

file(GLOB_RECURSE sources CONFIGURE_DEPENDS "*.cpp")

add_executable(test_cpp_doom ${sources})
target_link_libraries(test_cpp_doom Catch2::Catch2 lib_common_cpp_doom)
target_compile_definitions(test_cpp_doom PUBLIC CATCH_CONFIG_CONSOLE_WIDTH=300)
target_include_directories(test_cpp_doom PRIVATE ${CMAKE_SOURCE_DIR}/src)

add_test(NAME test_cpp_doom COMMAND test_cpp_doom)
add_subdirectory(cpp_doom)
add_subdirectory(dehacked)
8 changes: 8 additions & 0 deletions test/cpp_doom/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "*.cpp")

add_executable(test_cpp_doom ${sources})
target_link_libraries(test_cpp_doom Catch2::Catch2 lib_common_cpp_doom)
target_compile_definitions(test_cpp_doom PUBLIC CATCH_CONFIG_CONSOLE_WIDTH=300)
target_include_directories(test_cpp_doom PRIVATE ${CMAKE_SOURCE_DIR}/src)

add_test(NAME test_cpp_doom COMMAND test_cpp_doom)
File renamed without changes.
103 changes: 103 additions & 0 deletions test/cpp_doom/test_z_native.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#include <catch2/catch.hpp>

#include "z_zone.hpp"

TEST_CASE("Z_Init", "[z_native]") {
Z_Init();
}

TEST_CASE("Z_Malloc(PU_STATIC)", "[z_native]") {
void * ptr = Z_Malloc(10, PU_STATIC, nullptr);
REQUIRE(ptr != nullptr);
}

TEST_CASE("Z_Malloc(PU_LEVEL)", "[z_native]") {
void * ptr = Z_Malloc(10, PU_LEVEL, nullptr);
REQUIRE(ptr != nullptr);
}

TEST_CASE("Z_Malloc(PU_LEVSPEC)", "[z_native]") {
void * ptr = Z_Malloc(10, PU_LEVSPEC, nullptr);
REQUIRE(ptr != nullptr);
}

TEST_CASE("Z_Malloc(PU_LEVEL) and Z_Free", "[z_native]") {
void * ptr = Z_Malloc(10, PU_LEVEL, nullptr);
REQUIRE(ptr != nullptr);
Z_Free(ptr);
}

TEST_CASE("Z_Malloc(PU_LEVEL) and Z_Free and Z_Malloc(PU_LEVEL)", "[z_native]") {
void * ptr = Z_Malloc(10, PU_LEVEL, nullptr);
REQUIRE(ptr != nullptr);
Z_Free(ptr);
void * ptr2 = Z_Malloc(10, PU_LEVEL, nullptr);
REQUIRE(ptr2 != nullptr);
}

// Some compilers don't define __SANITIZE_ADDRESS__
#if defined(__has_feature)
# if __has_feature(address_sanitizer)
# if !defined(__SANITIZE_ADDRESS__)
# define __SANITIZE_ADDRESS__ // NOLINT
# endif // !defined(__SANITIZE_ADDRESS__)
# endif // __has_feature(address_sanitizer)
#endif // __has_feature

#ifndef __SANITIZE_ADDRESS__
struct memblock_t {
int id; // = ZONEID
int tag;
int size;
void ** user;
memblock_t * prev;
memblock_t * next;
};

long * where;
long what;

TEST_CASE("Z_ZOverwrite header", "[z_native]") {

void * guard = Z_Malloc(10, PU_LEVEL, nullptr);
REQUIRE(guard != nullptr);

void * ptr = Z_Malloc(10, PU_LEVEL, nullptr);
REQUIRE(ptr != nullptr);

void * guard2 = Z_Malloc(10, PU_LEVEL, nullptr);
REQUIRE(guard2 != nullptr);

// Corrupt header
where = nullptr;
what = 0x42424242;

auto * byte_ptr = reinterpret_cast<uint8_t *>(ptr);
auto * header = reinterpret_cast<memblock_t *>(byte_ptr - sizeof(memblock_t));
REQUIRE(header->tag == PU_LEVEL);
long * what_ptr = &what;
long ** where_ptr = &where;

auto distance = reinterpret_cast<uint8_t*>(&(header->next)) - reinterpret_cast<uint8_t*>(header);
if constexpr (sizeof(void *) == 8)
REQUIRE(distance == 32);
else
REQUIRE(distance == 20);

uint8_t * byte_where_ptr = reinterpret_cast<uint8_t*>(where_ptr);
uint8_t * adjusted_byte_where_ptr = byte_where_ptr - distance;

header->prev = reinterpret_cast<memblock_t *>(adjusted_byte_where_ptr);
header->next = reinterpret_cast<memblock_t *>(what_ptr);
// Corruption done

// Verify state
REQUIRE(where == nullptr);

Z_Free(ptr);

// Check if successful
REQUIRE(where != nullptr);
REQUIRE(*where == 0x42424242);
}
#endif // !__SANITIZE_ADDRESS__
File renamed without changes.
8 changes: 8 additions & 0 deletions test/dehacked/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "*.cpp")

add_executable(test_dehacked ${sources})
target_link_libraries(test_dehacked Catch2::Catch2 lib_common_dehacked)
target_compile_definitions(test_dehacked PUBLIC CATCH_CONFIG_CONSOLE_WIDTH=300)
target_include_directories(test_dehacked PRIVATE ${CMAKE_SOURCE_DIR}/src)

add_test(NAME test_dehacked COMMAND test_dehacked)
100 changes: 100 additions & 0 deletions test/dehacked/test_z_zone.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#include <catch2/catch.hpp>

#include "z_zone.hpp"

TEST_CASE("Z_Init", "[z_zone]") {
Z_Init();
REQUIRE(Z_ZoneSize() == 0x2000000);
}

TEST_CASE("Z_Malloc(PU_STATIC)", "[z_zone]") {
void * ptr = Z_Malloc(10, PU_STATIC, nullptr);
REQUIRE(ptr != nullptr);
}

TEST_CASE("Z_Malloc(PU_LEVEL)", "[z_zone]") {
void * ptr = Z_Malloc(10, PU_LEVEL, nullptr);
REQUIRE(ptr != nullptr);
}

TEST_CASE("Z_Malloc(PU_LEVSPEC)", "[z_zone]") {
void * ptr = Z_Malloc(10, PU_LEVSPEC, nullptr);
REQUIRE(ptr != nullptr);
}

TEST_CASE("Z_Malloc(PU_LEVEL) and Z_Free", "[z_zone]") {
void * ptr = Z_Malloc(10, PU_LEVEL, nullptr);
REQUIRE(ptr != nullptr);
Z_Free(ptr);
}

TEST_CASE("Z_Malloc(PU_LEVEL) and Z_Free and Z_Malloc(PU_LEVEL)", "[z_zone]") {
void * ptr = Z_Malloc(10, PU_LEVEL, nullptr);
REQUIRE(ptr != nullptr);
Z_Free(ptr);
void * ptr2 = Z_Malloc(10, PU_LEVEL, nullptr);
REQUIRE(ptr2 != nullptr);
REQUIRE(ptr == ptr2);
}

// Some compilers don't define __SANITIZE_ADDRESS__
#if defined(__has_feature)
# if __has_feature(address_sanitizer)
# if !defined(__SANITIZE_ADDRESS__)
# define __SANITIZE_ADDRESS__ // NOLINT
# endif // !defined(__SANITIZE_ADDRESS__)
# endif // __has_feature(address_sanitizer)
#endif // __has_feature

#ifndef __SANITIZE_ADDRESS__
struct memblock_t {
int size; // including the header and possibly tiny fragments
void ** user;
int tag; // PU_FREE if this is free
int id; // should be ZONEID
struct memblock_t * next;
struct memblock_t * prev;
};

long what;

memblock_t fake{
.size = 0,
.user = nullptr,
.tag = PU_FREE,
.id = 0,
.next = nullptr, // where
.prev = nullptr
};

TEST_CASE("Z_ZOverwrite header", "[z_zone]") {

void * guard = Z_Malloc(10, PU_LEVEL, nullptr);
REQUIRE(guard != nullptr);

void * ptr = Z_Malloc(10, PU_LEVEL, nullptr);
REQUIRE(ptr != nullptr);

void * guard2 = Z_Malloc(10, PU_LEVEL, nullptr);
REQUIRE(guard2 != nullptr);

what = 0x42424242;

// Corrupt header
auto * byte_ptr = reinterpret_cast<uint8_t *>(ptr);
auto * header = reinterpret_cast<memblock_t *>(byte_ptr - sizeof(memblock_t));
REQUIRE(header->tag == PU_LEVEL);
header->prev = &fake;
header->next = reinterpret_cast<memblock_t *>(&what);
// Corruption done

// Verify state
REQUIRE(header->prev->next == nullptr);

Z_Free(ptr);

// Check if successful
REQUIRE(header->prev->next != nullptr);
REQUIRE(*(reinterpret_cast<long*>(header->prev->next)) == 0x42424242);
}
#endif
2 changes: 2 additions & 0 deletions test/dehacked/tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
2 changes: 1 addition & 1 deletion textscreen/txt_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ txt_window_t * TXT_MessageBox(const char * title, cstring_view message, ...) {
va_list args;

va_start(args, message);
TXT_vsnprintf(buf, sizeof(buf), message, args);
TXT_vsnprintf(buf, sizeof(buf), message.c_str(), args);
va_end(args);

txt_window_t * window = TXT_NewWindow(title);
Expand Down