diff --git a/CMakeLists.txt b/CMakeLists.txt index 80492d1ef..79a900086 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.8.11) +cmake_minimum_required (VERSION 3.5.0) project (hyperscan C CXX) set (HS_MAJOR_VERSION 5) @@ -474,6 +474,9 @@ endif() if(CMAKE_CXX_COMPILER_ID MATCHES "Intel") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -diag-error 10006 -diag-disable 68 -diag-disable 177 -diag-disable 186 -diag-disable 2304 -diag-disable 2305 -diag-disable 2338 -diag-disable 1418 -diag-disable 1170 -diag-disable 3373 -diag-disable 279 -diag-disable=remark") endif() +if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12.0") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-stringop-overread -Wno-stringop-overflow") +endif() endif() if (NOT FAT_RUNTIME) diff --git a/src/db_protect.c b/src/db_protect.c index 8fab64e93..8ee3f832f 100644 --- a/src/db_protect.c +++ b/src/db_protect.c @@ -24,6 +24,9 @@ implied warranties, other than those that are expressly stated in the License. * memory may not be page-aligned or mmap-backed). */ +#ifndef _WIN32 +#define _GNU_SOURCE +#endif #include "allocator.h" #include "database.h" #include "hs_common.h" diff --git a/src/nfa/nfa_rev_api.h b/src/nfa/nfa_rev_api.h index ea9bc411c..7fab4c2de 100644 --- a/src/nfa/nfa_rev_api.h +++ b/src/nfa/nfa_rev_api.h @@ -104,7 +104,7 @@ size_t nfaRevAccel_i(const struct NFA *nfa, const u8 *buffer, size_t length) { break; case ACCEL_RDEOD: DEBUG_PRINTF("ACCEL_RDEOD\n"); - if (length < nfa->rAccelOffset + 1) { + if (length < (size_t)nfa->rAccelOffset + 1) { break; } if (unaligned_load_u16(buffer + length - nfa->rAccelOffset) != @@ -114,7 +114,7 @@ size_t nfaRevAccel_i(const struct NFA *nfa, const u8 *buffer, size_t length) { break; case ACCEL_RDEOD_NOCASE: DEBUG_PRINTF("ACCEL_RDEOD_NOCASE\n"); - if (length < nfa->rAccelOffset + 1) { + if (length < (size_t)nfa->rAccelOffset + 1) { break; } if ((unaligned_load_u16(buffer + length - nfa->rAccelOffset) & diff --git a/unit/hyperscan/arg_checks.cpp b/unit/hyperscan/arg_checks.cpp index 6a2fa650d..8eea43d07 100644 --- a/unit/hyperscan/arg_checks.cpp +++ b/unit/hyperscan/arg_checks.cpp @@ -28,6 +28,12 @@ #include "config.h" +#include +#ifndef _WIN32 +#include +#include +#endif + #include "gtest/gtest.h" #include "hs.h" #include "database.h" @@ -57,36 +63,70 @@ int singleHandler(unsigned id, unsigned long long from, namespace /* anonymous */ { +#ifndef _WIN32 +static void makeDatabaseWritable(hs_database *db) { + if (!db) { + return; + } + long ps_raw = sysconf(_SC_PAGESIZE); + if (ps_raw <= 0) { + return; + } + size_t ps = (size_t)ps_raw; + /* Verify page size is a power of two. */ + if ((ps & (ps - 1)) != 0) { + return; + } + if ((uintptr_t)db & (ps - 1)) { + return; + } + size_t db_len = sizeof(struct hs_database) + db->length; + /* Guard against overflow in round-up arithmetic. */ + if (db_len > SIZE_MAX - ps) { + return; + } + size_t rounded = (db_len + ps - 1) & ~(ps - 1); + if (rounded < db_len || rounded == 0) { + return; + } + int ret = mprotect(db, rounded, PROT_READ | PROT_WRITE); + (void)ret; /* intentionally ignore in test code */ +} +#else +static void makeDatabaseWritable(hs_database *db) { + if (!db) { + return; + } + size_t db_len = sizeof(struct hs_database) + db->length; + hs_db_unprotect(db, db_len); +} +#endif + // Break the magic number of the given database. void breakDatabaseMagic(hs_database *db) { + makeDatabaseWritable(db); // database magic should be 0xdbdb at the start - size_t db_len = sizeof(struct hs_database) + db->length; - hs_db_unprotect(db, db_len); ASSERT_TRUE(memcmp("\xdb\xdb", db, 2) == 0); *(char *)db = 0xdc; } // Break the version number of the given database. void breakDatabaseVersion(hs_database *db) { + makeDatabaseWritable(db); // database version is the second u32 - size_t db_len = sizeof(struct hs_database) + db->length; - hs_db_unprotect(db, db_len); *((char *)db + 4) += 1; } // Break the platform data of the given database. void breakDatabasePlatform(hs_database *db) { + makeDatabaseWritable(db); // database platform is an aligned u64a 16 bytes in - size_t db_len = sizeof(struct hs_database) + db->length; - hs_db_unprotect(db, db_len); memset((char *)db + 16, 0xff, 8); } // Break the alignment of the bytecode for the given database. void breakDatabaseBytecode(hs_database *db) { - // bytecode ptr is a u32 at offsetof(hs_database, bytecode) - size_t db_len = sizeof(struct hs_database) + db->length; - hs_db_unprotect(db, db_len); + makeDatabaseWritable(db); unsigned int *bytecode = (unsigned int *)((char *)db + offsetof(struct hs_database, bytecode)); ASSERT_NE(0U, *bytecode); ASSERT_EQ(0U, (size_t)((char *)db + *bytecode) % 16U); @@ -916,7 +956,6 @@ TEST(HyperscanArgChecks, ScanBlockBrokenDatabaseMagic) { ASSERT_TRUE(scratch != nullptr); // break the database here, after scratch alloc - size_t db_len1 = sizeof(struct hs_database) + db->length; breakDatabaseMagic(db); err = hs_scan(db, "data", 4, 0, scratch, dummy_cb, nullptr); @@ -925,7 +964,7 @@ TEST(HyperscanArgChecks, ScanBlockBrokenDatabaseMagic) { // teardown err = hs_free_scratch(scratch); ASSERT_EQ(HS_SUCCESS, err); - hs_db_free(db, db_len1); + hs_free_database(db); } // hs_scan: Call with a database with broken version @@ -1120,7 +1159,6 @@ TEST(HyperscanArgChecks, ScanVectorBrokenDatabaseMagic) { ASSERT_TRUE(scratch != nullptr); // break the database here, after scratch alloc - size_t db_len2 = sizeof(struct hs_database) + db->length; breakDatabaseMagic(db); const char *data[] = {"data", "data"}; @@ -1131,7 +1169,7 @@ TEST(HyperscanArgChecks, ScanVectorBrokenDatabaseMagic) { // teardown err = hs_free_scratch(scratch); ASSERT_EQ(HS_SUCCESS, err); - hs_db_free(db, db_len2); + hs_free_database(db); } // hs_scan_vector: Call with a database with broken version @@ -1400,7 +1438,6 @@ TEST(HyperscanArgChecks, AllocScratchBadDatabaseMagic) { ASSERT_EQ(HS_SUCCESS, err); ASSERT_TRUE(db != nullptr); - size_t db_len3 = sizeof(struct hs_database) + db->length; breakDatabaseMagic(db); hs_scratch_t *scratch = nullptr; @@ -1408,7 +1445,7 @@ TEST(HyperscanArgChecks, AllocScratchBadDatabaseMagic) { ASSERT_EQ(HS_INVALID, err); // teardown - hs_db_free(db, db_len3); + hs_free_database(db); } // hs_alloc_scratch: Call with broken database version @@ -1490,7 +1527,7 @@ TEST(HyperscanArgChecks, AllocScratchBadDatabaseCRC) { ASSERT_EQ(HS_SUCCESS, err); // for want of a better case, corrupt the "middle byte" of the database. - hs_db_unprotect(db, len); + makeDatabaseWritable(db); char *mid = (char *)db + len/2; *mid += 17; @@ -1575,14 +1612,14 @@ TEST(HyperscanArgChecks, StreamSizeBogusDatabase) { ASSERT_EQ(HS_SUCCESS, err); ASSERT_LT(0U, len); - hs_db_unprotect(db, len); + makeDatabaseWritable(db); memset(db, 0xf0, len); size_t sz; err = hs_stream_size(db, &sz); ASSERT_EQ(HS_INVALID, err); - hs_db_free(db, len); + hs_free_database(db); } // hs_stream_size: Call with a block-mode database diff --git a/unit/hyperscan/single.cpp b/unit/hyperscan/single.cpp index bbe116a0e..6732fb33b 100644 --- a/unit/hyperscan/single.cpp +++ b/unit/hyperscan/single.cpp @@ -244,9 +244,8 @@ class HyperscanTestRuntime size_t origSize; err = hs_database_size(db, &origSize); ASSERT_EQ(HS_SUCCESS, err); - hs_db_unprotect(db, origSize); - memset(db, 0xff, origSize); - hs_db_free(db, origSize); + hs_free_database(db); + db = nullptr; // relocate to 16 different alignments, ensuring that we can // deserialize from any string