Преглед изворни кода

Add sanitzer checks

Signed-off-by: Martin Melik Merkumians <martin.melik@gmail.com>
Martin Melik Merkumians пре 2 недеља
родитељ
комит
1ce151a5a3

+ 15 - 15
.github/workflows/WORKFLOWS.md

@@ -70,14 +70,14 @@ Central MegaLinter configuration with:
 
 ### When Does Each Workflow Run?
 
-| Event | CI (Fast) | Exhaustive |
-|-------|-----------|------------|
-| Push to `master` | ✅ | ❌ |
-| Pull request | ✅ | ❌ |
-| Push to `release/*` | ❌ | ✅ |
-| Version tag (`v*`) | ❌ | ✅ |
-| Nightly (3 AM UTC) | ❌ | ✅ |
-| Manual trigger | ❌ | ✅ |
+| Event               | CI (Fast) | Exhaustive |
+|---------------------|-----------|------------|
+| Push to `master`    | ✅         | ❌          |
+| Pull request        | ✅         | ❌          |
+| Push to `release/*` | ❌         | ✅          |
+| Version tag (`v*`)  | ❌         | ✅          |
+| Nightly (3 AM UTC)  | ❌         | ✅          |
+| Manual trigger      | ❌         | ✅          |
 
 ## Benefits of This Approach
 
@@ -148,13 +148,13 @@ CPPCHECK_ARGUMENTS: --check-level=exhaustive --inline-suppr
 
 The new structure maintains all functionality from `build.yml`:
 
-| Old Feature | New Location | Changes |
-|------------|--------------|---------|
-| MegaLinter | `ci.yml` → lint | Split into standard/exhaustive |
-| Build & Test | `ci.yml` → build-test | Added parallel execution |
-| Coverage | `ci.yml` → build-test | Enhanced reporting |
-| Auto-fixes | `ci.yml` → lint | Simplified logic |
-| Release validation | NEW: `exhaustive-analysis.yml` | Added thorough checks |
+| Old Feature        | New Location                   | Changes                        |
+|--------------------|--------------------------------|--------------------------------|
+| MegaLinter         | `ci.yml` → lint                | Split into standard/exhaustive |
+| Build & Test       | `ci.yml` → build-test          | Added parallel execution       |
+| Coverage           | `ci.yml` → build-test          | Enhanced reporting             |
+| Auto-fixes         | `ci.yml` → lint                | Simplified logic               |
+| Release validation | NEW: `exhaustive-analysis.yml` | Added thorough checks          |
 
 ## Manual Workflow Execution
 

+ 1 - 1
.github/workflows/exhaustive-analysis.yml

@@ -13,7 +13,7 @@ on:
 
   # Nightly exhaustive analysis
   schedule:
-    - cron: "0 3 * * *"  # 3 AM UTC daily
+    - cron: "0 3 * * *" # 3 AM UTC daily
 
   # Manual trigger
   workflow_dispatch:

+ 4 - 4
.mega-linter.yml

@@ -11,7 +11,7 @@ APPLY_FIXES: all
 
 # Linters configuration
 DISABLE_LINTERS:
-  - SPELL_CSPELL  # Disabled as per original config
+  - SPELL_CSPELL # Disabled
 
 # Formatter specific configuration
 C_CLANG_FORMAT_ARGUMENTS: "--style=file"
@@ -34,10 +34,10 @@ COPYPASTE_JSCPD_ARGUMENTS:
 
 # Fix for Link Checker (Lychee)
 SPELL_LYCHEE_ARGUMENTS:
-  # 1. Ignore the broken GitHub variable placeholders
-  # 2. Ignore local file links that are failing due to path nesting
   - "--exclude"
-  - 'https://github\.com/.*\$'
+  - "https://github/.*"
+  - "--exclude"
+  - 'https://github\.com/.*'
   - "--exclude-path"
   - "source/tests/ports/CHECKENCAPSULATIONINACTIVITY_TESTS.md"
 

+ 10 - 10
CPPUTEST_ASAN_COMPATIBILITY.md

@@ -76,15 +76,15 @@ ASAN_OPTIONS="verbosity=0" ./tests/OpENer_Tests -g NetworkHandlerSecurity
 
 ## Memory Safety Coverage
 
-| Feature | CppUTest | ASAN | Both |
-|---------|----------|------|------|
-| Leak detection | ✓ | ✓ | ASAN only |
-| Buffer overflow | - | ✓ | ✓ |
-| Use-after-free | - | ✓ | ✓ |
-| Double-free | - | ✓ | ✓ |
-| Integer overflow | - | ✓ (UBSAN) | ✓ |
-| Stack issues | - | ✓ | ✓ |
-| Uninitialized reads | - | Limited | Limited |
+| Feature             | CppUTest | ASAN      | Both      |
+|---------------------|----------|-----------|-----------|
+| Leak detection      | ✓        | ✓         | ASAN only |
+| Buffer overflow     | -        | ✓         | ✓         |
+| Use-after-free      | -        | ✓         | ✓         |
+| Double-free         | -        | ✓         | ✓         |
+| Integer overflow    | -        | ✓ (UBSAN) | ✓         |
+| Stack issues        | -        | ✓         | ✓         |
+| Uninitialized reads | -        | Limited   | Limited   |
 
 **Recommendation**: Use ASAN for comprehensive memory safety testing.
 
@@ -106,7 +106,7 @@ echo "Exit code: $?"
 ## References
 
 - **CppUTest Memory Management**: Uses `CHECK_EQUAL_TEXT`, `CHECK_EQUAL_NOCASE_TEXT` for memory checks
-- **ASAN Documentation**: https://github.com/google/sanitizers/wiki/AddressSanitizer
+- **ASAN Documentation**: <https://github.com/google/sanitizers/wiki/AddressSanitizer>
 - **Best Practices**: Disable CppUTest's memory checking when using compiler sanitizers
 
 ## Future Improvements

+ 12 - 12
SANITIZER_GUIDE.md

@@ -100,13 +100,13 @@ When ASAN detects an error, it produces output like:
 
 ### Common ASAN Error Types
 
-| Error | Cause | Fix |
-|-------|-------|-----|
-| `heap-buffer-overflow` | Writing beyond allocated heap buffer | Validate buffer size before write |
-| `stack-buffer-overflow` | Writing beyond stack array | Check array bounds |
-| `use-after-free` | Accessing freed memory | Don't use pointer after free |
-| `memory-leak` | Allocated memory never freed | Add appropriate free/cleanup |
-| `double-free` | Freeing same pointer twice | Track free() calls |
+| Error                   | Cause                                | Fix                               |
+|-------------------------|--------------------------------------|-----------------------------------|
+| `heap-buffer-overflow`  | Writing beyond allocated heap buffer | Validate buffer size before write |
+| `stack-buffer-overflow` | Writing beyond stack array           | Check array bounds                |
+| `use-after-free`        | Accessing freed memory               | Don't use pointer after free      |
+| `memory-leak`           | Allocated memory never freed         | Add appropriate free/cleanup      |
+| `double-free`           | Freeing same pointer twice           | Track free() calls                |
 
 ## Security Test Suite
 
@@ -201,11 +201,11 @@ export UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1:verbosity=2"
 
 Sanitizers add significant overhead:
 
-| Metric | Normal | ASAN | UBSAN | Both |
-|--------|--------|------|-------|------|
-| Execution Speed | 1x | 2-4x slower | 1.1-1.5x slower | 2.5-5x slower |
-| Memory Overhead | 1x | 2-3x larger | ~1x | 2-3x larger |
-| Compile Time | Normal | +30% | +20% | +50% |
+| Metric          | Normal | ASAN        | UBSAN           | Both          |
+|-----------------|--------|-------------|-----------------|---------------|
+| Execution Speed | 1x     | 2-4x slower | 1.1-1.5x slower | 2.5-5x slower |
+| Memory Overhead | 1x     | 2-3x larger | ~1x             | 2-3x larger   |
+| Compile Time    | Normal | +30%        | +20%            | +50%          |
 
 **Recommendation**: Use sanitizers during development and CI, use optimized builds for production.
 

+ 6 - 6
build_with_sanitizers.sh

@@ -29,8 +29,8 @@ BUILD_DIR="${PROJECT_ROOT}/build_sanitizer"
 SANITIZER_TYPE="${1:-both}"
 
 if [[ ! "$SANITIZER_TYPE" =~ ^(asan|ubsan|both)$ ]]; then
-    echo "Usage: $0 [asan|ubsan|both]"
-    exit 1
+	echo "Usage: $0 [asan|ubsan|both]"
+	exit 1
 fi
 
 echo "=============================================="
@@ -48,13 +48,13 @@ cd "$BUILD_DIR"
 CMAKE_ARGS="-DCMAKE_BUILD_TYPE=Debug -DOpENer_PLATFORM=POSIX -DOpENer_TESTS=ON"
 
 if [[ "$SANITIZER_TYPE" == "asan" || "$SANITIZER_TYPE" == "both" ]]; then
-    CMAKE_ARGS="$CMAKE_ARGS -DENABLE_ADDRESS_SANITIZER=ON"
-    echo "[+] AddressSanitizer enabled"
+	CMAKE_ARGS="$CMAKE_ARGS -DENABLE_ADDRESS_SANITIZER=ON"
+	echo "[+] AddressSanitizer enabled"
 fi
 
 if [[ "$SANITIZER_TYPE" == "ubsan" || "$SANITIZER_TYPE" == "both" ]]; then
-    CMAKE_ARGS="$CMAKE_ARGS -DENABLE_UNDEFINED_SANITIZER=ON"
-    echo "[+] UndefinedBehaviorSanitizer enabled"
+	CMAKE_ARGS="$CMAKE_ARGS -DENABLE_UNDEFINED_SANITIZER=ON"
+	echo "[+] UndefinedBehaviorSanitizer enabled"
 fi
 
 echo ""

+ 20 - 20
run_sanitizer_tests.sh

@@ -21,24 +21,24 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
 
 # Determine build directory
 if [ -n "$1" ] && [ -d "$1" ]; then
-    BUILD_DIR="$1"
+	BUILD_DIR="$1"
 elif [ -d "${SCRIPT_DIR}/build_sanitizer" ]; then
-    BUILD_DIR="${SCRIPT_DIR}/build_sanitizer"
+	BUILD_DIR="${SCRIPT_DIR}/build_sanitizer"
 elif [ -d "${SCRIPT_DIR}/build" ]; then
-    BUILD_DIR="${SCRIPT_DIR}/build"
+	BUILD_DIR="${SCRIPT_DIR}/build"
 else
-    echo "Error: Cannot find build directory"
-    echo "Usage: $0 [build_dir] [test_filter]"
-    exit 1
+	echo "Error: Cannot find build directory"
+	echo "Usage: $0 [build_dir] [test_filter]"
+	exit 1
 fi
 
 TEST_FILTER="${2:-}"
 TEST_EXECUTABLE="${BUILD_DIR}/tests/OpENer_Tests"
 
 if [ ! -f "$TEST_EXECUTABLE" ]; then
-    echo "Error: Test executable not found at $TEST_EXECUTABLE"
-    echo "Build with: ./build_with_sanitizers.sh"
-    exit 1
+	echo "Error: Test executable not found at $TEST_EXECUTABLE"
+	echo "Build with: ./build_with_sanitizers.sh"
+	exit 1
 fi
 
 echo "=============================================="
@@ -60,10 +60,10 @@ echo ""
 # Run tests
 TEST_ARGS="-v -c"
 if [ -n "$TEST_FILTER" ]; then
-    TEST_ARGS="$TEST_ARGS -g $TEST_FILTER"
-    echo "Running tests matching: $TEST_FILTER"
+	TEST_ARGS="$TEST_ARGS -g $TEST_FILTER"
+	echo "Running tests matching: $TEST_FILTER"
 else
-    echo "Running all tests..."
+	echo "Running all tests..."
 fi
 
 echo ""
@@ -73,24 +73,24 @@ TEST_RESULT=$?
 echo ""
 echo "=============================================="
 if [ "$TEST_RESULT" -eq 0 ]; then
-    echo "✓ All tests passed!"
+	echo "✓ All tests passed!"
 else
-    echo "✗ Tests failed with exit code: $TEST_RESULT"
+	echo "✗ Tests failed with exit code: $TEST_RESULT"
 fi
 echo "=============================================="
 echo ""
 
 # Check for sanitizer logs
 if [ -f "asan.log" ]; then
-    echo "AddressSanitizer detected issues:"
-    echo "See asan.log for details"
-    echo ""
+	echo "AddressSanitizer detected issues:"
+	echo "See asan.log for details"
+	echo ""
 fi
 
 if [ -f "ubsan.log" ]; then
-    echo "UndefinedBehaviorSanitizer detected issues:"
-    echo "See ubsan.log for details"
-    echo ""
+	echo "UndefinedBehaviorSanitizer detected issues:"
+	echo "See ubsan.log for details"
+	echo ""
 fi
 
 exit $TEST_RESULT

+ 13 - 12
source/src/cip/cipstringi.c

@@ -98,7 +98,7 @@ void CipStringIDeepCopyInternalString(CipStringIStruct* const to,
     case kCipShortString: {
       CipShortString* const toString   = (CipShortString*)to->string;
       CipShortString* const fromString = (CipShortString*)from->string;
-      toString->length           = fromString->length;
+      toString->length                 = fromString->length;
       toString->string = CipCalloc(toString->length, sizeof(CipOctet));
       memcpy(toString->string,
              fromString->string,
@@ -107,8 +107,8 @@ void CipStringIDeepCopyInternalString(CipStringIStruct* const to,
     case kCipString: {
       CipString* const toString   = (CipString*)to->string;
       CipString* const fromString = (CipString*)from->string;
-      toString->length      = fromString->length;
-      toString->string      = CipCalloc(toString->length, sizeof(CipOctet));
+      toString->length            = fromString->length;
+      toString->string = CipCalloc(toString->length, sizeof(CipOctet));
       memcpy(toString->string,
              fromString->string,
              sizeof(CipOctet) * toString->length);
@@ -116,7 +116,7 @@ void CipStringIDeepCopyInternalString(CipStringIStruct* const to,
     case kCipString2: {
       CipString2* const toString   = (CipString2*)to->string;
       CipString2* const fromString = (CipString2*)from->string;
-      toString->length       = fromString->length;
+      toString->length             = fromString->length;
       toString->string = CipCalloc(toString->length, 2 * sizeof(CipOctet));
       memcpy(toString->string,
              fromString->string,
@@ -125,8 +125,8 @@ void CipStringIDeepCopyInternalString(CipStringIStruct* const to,
     case kCipStringN: {
       CipStringN* const toString   = (CipStringN*)to->string;
       CipStringN* const fromString = (CipStringN*)from->string;
-      toString->length       = fromString->length;
-      toString->size         = fromString->size;
+      toString->length             = fromString->length;
+      toString->size               = fromString->size;
       toString->string =
         CipCalloc(toString->length, toString->size * sizeof(CipOctet));
       memcpy(toString->string,
@@ -251,9 +251,9 @@ bool CipStringICompare(const CipStringI* const stringI_1,
       } break;
       case kCipStringN: {
         const CipUint length = ((CipStringN*)string_1)->length;
-        const CipUint size   = ((CipStringN*)string_1)->size;  // bytes per symbol
-        len_1          = length * size;
-        string_1_data  = ((CipStringN*)string_1)->string;
+        const CipUint size = ((CipStringN*)string_1)->size;  // bytes per symbol
+        len_1              = length * size;
+        string_1_data      = ((CipStringN*)string_1)->string;
       } break;
       default:
         OPENER_TRACE_ERR("CIP File: No valid String type received!\n");
@@ -283,9 +283,10 @@ bool CipStringICompare(const CipStringI* const stringI_1,
         } break;
         case kCipStringN: {
           const CipUint length = ((CipStringN*)string_2)->length;
-          const CipUint size   = ((CipStringN*)string_2)->size;  // bytes per symbol
-          len_2          = length * size;
-          string_2_data  = ((CipStringN*)string_2)->string;
+          const CipUint size =
+            ((CipStringN*)string_2)->size;  // bytes per symbol
+          len_2         = length * size;
+          string_2_data = ((CipStringN*)string_2)->string;
         } break;
         default:
           OPENER_TRACE_ERR("CIP File: No valid String type received!\n");

+ 0 - 1
source/tests/OpENerTests.cpp

@@ -8,7 +8,6 @@
 
 #include <csetjmp>
 #include <cstdio>
-
 #include <stdexcept>
 
 #include "CppUTest/TestRegistry.h"