Skip to content
Closed
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
119 changes: 119 additions & 0 deletions score/evaluation/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# *******************************************************************************
# Copyright (c) 2025 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************
#
# BUILD file for score/evaluation
#
# Each cc_library target corresponds to one evaluation scenario file.
# The cc_binary target "evaluation_all" links every library and provides
# a single compilable artefact that the code-review tool can analyse.
#
# NOTE: These targets intentionally contain anti-patterns and bad practices.
# They are NOT suitable for production use and exist solely for
# evaluating the capability of automated code-review tools.
# *******************************************************************************

load("@rules_cc//cc:defs.bzl", "cc_binary")

alias(
name = "solid_violations",
actual = "//score/evaluation/solid:solid_violations",
)

alias(
name = "memory_issues",
actual = "//score/evaluation/memory:memory_issues",
)

alias(
name = "non_idiomatic_cpp",
actual = "//score/evaluation/idiomatic:non_idiomatic_cpp",
)

alias(
name = "modern_cpp_syntax",
actual = "//score/evaluation/modern_cpp:modern_cpp_syntax",
)

alias(
name = "design_patterns",
actual = "//score/evaluation/patterns:design_patterns",
)

alias(
name = "code_optimization",
actual = "//score/evaluation/optimization:code_optimization",
)

alias(
name = "safe_cpp",
actual = "//score/evaluation/safety:safe_cpp",
)

alias(
name = "security_issues",
actual = "//score/evaluation/security:security_issues",
)

alias(
name = "design_faults",
actual = "//score/evaluation/design:design_faults",
)

alias(
name = "concurrency_issues",
actual = "//score/evaluation/concurrency:concurrency_issues",
)

alias(
name = "exception_error_handling",
actual = "//score/evaluation/exception_handling:exception_error_handling",
)

alias(
name = "unit_test_quality",
actual = "//score/evaluation/unit_test_quality:unit_test_quality",
)

alias(
name = "template_metaprogramming_issues",
actual = "//score/evaluation/template_metaprogramming:template_metaprogramming_issues",
)

alias(
name = "unit_test_quality_test",
actual = "//score/evaluation/unit_test_quality:unit_test_quality_test",
)

# ---------------------------------------------------------------------------
# Aggregate binary – compiles all evaluation scenarios together.
# ---------------------------------------------------------------------------
cc_binary(
name = "evaluation_all",
srcs = ["evaluation_main.cpp"],
visibility = ["//visibility:public"],
deps = [
"//score/evaluation/concurrency:concurrency_issues",
"//score/evaluation/design:design_faults",
"//score/evaluation/exception_handling:exception_error_handling",
"//score/evaluation/idiomatic:non_idiomatic_cpp",
"//score/evaluation/memory:memory_issues",
"//score/evaluation/modern_cpp:modern_cpp_syntax",
"//score/evaluation/optimization:code_optimization",
"//score/evaluation/patterns:design_patterns",
"//score/evaluation/security:security_issues",
"//score/evaluation/safety:safe_cpp",
"//score/evaluation/solid:solid_violations",
"//score/evaluation/template_metaprogramming:template_metaprogramming_issues",
"//score/evaluation/unit_test_quality:unit_test_quality",
],
)
29 changes: 29 additions & 0 deletions score/evaluation/EVALUATION_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Evaluation Guide (Root Index)

This root document is intentionally trimmed.
Use the per-directory guides for detailed test conditions and expected review comments.

## Per-Directory Guides

| Directory | Guide |
|---|---|
| `solid/` | [`solid/EVALUATION_GUIDE.md`](solid/EVALUATION_GUIDE.md) |
| `memory/` | [`memory/EVALUATION_GUIDE.md`](memory/EVALUATION_GUIDE.md) |
| `idiomatic/` | [`idiomatic/EVALUATION_GUIDE.md`](idiomatic/EVALUATION_GUIDE.md) |
| `modern_cpp/` | [`modern_cpp/EVALUATION_GUIDE.md`](modern_cpp/EVALUATION_GUIDE.md) |
| `patterns/` | [`patterns/EVALUATION_GUIDE.md`](patterns/EVALUATION_GUIDE.md) |
| `optimization/` | [`optimization/EVALUATION_GUIDE.md`](optimization/EVALUATION_GUIDE.md) |
| `security/` | [`security/EVALUATION_GUIDE.md`](security/EVALUATION_GUIDE.md) |
| `safety/` | [`safety/EVALUATION_GUIDE.md`](safety/EVALUATION_GUIDE.md) |
| `design/` | [`design/EVALUATION_GUIDE.md`](design/EVALUATION_GUIDE.md) |
| `concurrency/` | [`concurrency/EVALUATION_GUIDE.md`](concurrency/EVALUATION_GUIDE.md) |
| `exception_handling/` | [`exception_handling/EVALUATION_GUIDE.md`](exception_handling/EVALUATION_GUIDE.md) |
| `template_metaprogramming/` | [`template_metaprogramming/EVALUATION_GUIDE.md`](template_metaprogramming/EVALUATION_GUIDE.md) |
| `unit_test_quality/` | [`unit_test_quality/EVALUATION_GUIDE.md`](unit_test_quality/EVALUATION_GUIDE.md) |

## How to Use

1. Review code changes folder-by-folder.
2. Open the corresponding local `EVALUATION_GUIDE.md`.
3. Compare tool comments against expected findings in that local guide.
4. Record coverage per tag (`SV-*`, `MI-*`, `UT-*`, etc.) in your review notes.
13 changes: 13 additions & 0 deletions score/evaluation/concurrency/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# *******************************************************************************
# Copyright (c) 2025 Contributors to the Eclipse Foundation
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************

load("@rules_cc//cc:defs.bzl", "cc_library")

cc_library(
name = "concurrency_issues",
hdrs = ["concurrency_issues.h"],
visibility = ["//visibility:public"],
)
17 changes: 17 additions & 0 deletions score/evaluation/concurrency/EVALUATION_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Concurrency Evaluation Guide

## Scope
- **Source file:** `concurrency_issues.h`
- **Goal:** Verify tool catches race conditions, synchronization mistakes, and thread-lifetime bugs.

## Test Conditions and Expected Review Comments
- **CI-01:** Data race on plain shared counter.
- **CI-02:** Manual lock/unlock without RAII (exception safety deadlock risk).
- **CI-03:** Broken double-checked init pattern / memory-ordering concerns.
- **CI-04:** Deadlock from inconsistent lock ordering.
- **CI-05:** Condition-variable wait not predicate-safe for spurious wakeups.
- **CI-06:** Detached thread captures stack reference (dangling reference risk).
- **CI-07:** Check-then-act race despite atomic variable.

## Pass Criteria
- Tool should identify concrete interleavings/failure modes and propose robust synchronization patterns (`lock_guard`, `scoped_lock`, predicate waits, CAS loops).
208 changes: 208 additions & 0 deletions score/evaluation/concurrency/concurrency_issues.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
// *******************************************************************************
// Copyright (c) 2025 Contributors to the Eclipse Foundation
//
// See the NOTICE file(s) distributed with this work for additional
// information regarding copyright ownership.
//
// This program and the accompanying materials are made available under the
// terms of the Apache License Version 2.0 which is available at
// https://www.apache.org/parameters/LICENSE-2.0
//
// SPDX-License-Identifier: Apache-2.0
// *******************************************************************************

/// @file concurrency_issues.h
/// @brief Concurrency and thread-safety issues for code-review tool evaluation.
///
/// Issues planted (see EVALUATION_GUIDE.md §9 for expected review comments):
/// [CI-01] Data race: shared counter incremented without synchronisation.
/// [CI-02] Mutex locked but not protected by RAII lock guard – leak on exception.
/// [CI-03] Double-checked locking without std::atomic – broken on modern hardware.
/// [CI-04] Deadlock: two mutexes acquired in inconsistent order across two functions.
/// [CI-05] Condition variable spurious wakeup not handled (while replaced by if).
/// [CI-06] Detached thread writing to stack variable of the spawning scope.
/// [CI-07] std::atomic<int> used for a compound check-then-act – still a TOCTOU race.

#ifndef SCORE_EVALUATION_CONCURRENCY_ISSUES_H
#define SCORE_EVALUATION_CONCURRENCY_ISSUES_H

#include <atomic>
#include <condition_variable>
#include <mutex>
#include <string>
#include <thread>

namespace score
{
namespace evaluation
{

// ---------------------------------------------------------------------------
// [CI-01] Data race on shared counter – no synchronisation.
// ---------------------------------------------------------------------------
class UnsafeCounter
{
public:
void Increment() { ++count_; } // [CI-01] non-atomic, non-locked; data race
int Get() const { return count_; }

private:
int count_{0}; // should be std::atomic<int> or guarded by a mutex
};

// ---------------------------------------------------------------------------
// [CI-02] Manual mutex lock/unlock without RAII – leak on exception.
// ---------------------------------------------------------------------------
class ManualLockUser
{
public:
void Write(const std::string& data)
{
mtx_.lock(); // [CI-02] if anything between lock and unlock throws,
ProcessData(data); // the mutex is never unlocked → deadlock.
mtx_.unlock(); // Use std::lock_guard<std::mutex> lk(mtx_);
}

private:
static void ProcessData(const std::string& /*data*/)
{
// may throw
}

std::mutex mtx_;
};

// ---------------------------------------------------------------------------
// [CI-03] Double-checked locking without proper atomics / memory fences.
// ---------------------------------------------------------------------------
class BrokenLazyInit
{
public:
// [CI-03] initialised_ is a plain bool – reads/writes are not atomic.
// A second thread may observe initialised_ == true before the
// constructor of resource_ has completed (memory reorder).
// Use std::atomic<bool> with acquire/release semantics or call_once.
void EnsureInitialised()
{
if (!initialised_) // first check, no lock
{
std::lock_guard<std::mutex> lk(mtx_);
if (!initialised_) // second check, under lock
{
resource_ = 42;
initialised_ = true; // reorder: may be visible before resource_ = 42
}
}
}

int GetResource() const { return resource_; }

private:
bool initialised_{false}; // [CI-03] should be std::atomic<bool>
int resource_{0};
std::mutex mtx_;
};

// ---------------------------------------------------------------------------
// [CI-04] Deadlock: mutexes acquired in opposite order in two different paths.
// ---------------------------------------------------------------------------
class DeadlockProne
{
public:
// Thread A calls TransferAB, Thread B calls TransferBA simultaneously → deadlock.
void TransferAB(int amount)
{
std::lock_guard<std::mutex> la(mtx_a_); // locks A first
std::lock_guard<std::mutex> lb(mtx_b_); // then B
balance_a_ -= amount;
balance_b_ += amount;
}

void TransferBA(int amount)
{
std::lock_guard<std::mutex> lb(mtx_b_); // locks B first [CI-04]
std::lock_guard<std::mutex> la(mtx_a_); // then A – opposite order
balance_b_ -= amount;
balance_a_ += amount;
}

private:
std::mutex mtx_a_;
std::mutex mtx_b_;
int balance_a_{1000};
int balance_b_{1000};
};

// ---------------------------------------------------------------------------
// [CI-05] Condition variable spurious wakeup handled with 'if' instead of 'while'.
// ---------------------------------------------------------------------------
class SpuriousWakeupBug
{
public:
void Wait()
{
std::unique_lock<std::mutex> lk(mtx_);
// [CI-05] Using if: spurious wakeup proceeds even when ready_ is false.
// Must use while (!ready_) or the predicate overload of wait().
if (!ready_) cv_.wait(lk);
// Proceed – but ready_ might still be false after a spurious wakeup.
}

void Signal()
{
std::lock_guard<std::mutex> lk(mtx_);
ready_ = true;
cv_.notify_one();
}

private:
std::mutex mtx_;
std::condition_variable cv_;
bool ready_{false};
};

// ---------------------------------------------------------------------------
// [CI-06] Detached thread capturing reference to local stack variable.
// ---------------------------------------------------------------------------
inline void StartDetachedThread()
{
std::string local_config = "config_data";

// [CI-06] local_config is on the stack of StartDetachedThread().
// After the function returns, the thread holds a dangling reference.
std::thread t([&local_config]()
{
// Accessing local_config after StartDetachedThread() returns → UB.
(void)local_config;
});
t.detach();
// Function returns here; local_config destroyed; thread still running.
}

// ---------------------------------------------------------------------------
// [CI-07] Compound check-then-act on std::atomic is still a TOCTOU race.
// ---------------------------------------------------------------------------
class TocTouAtomic
{
public:
// [CI-07] Even though count_ is atomic, the if-check and decrement are
// two separate operations. Another thread can decrement between the
// check and the decrement, driving count_ below zero.
void ConsumeIfAvailable()
{
if (count_.load() > 0) // check
{
--count_; // act – not atomic with the check
}
}

void Produce() { ++count_; }

private:
std::atomic<int> count_{0};
};

} // namespace evaluation
} // namespace score

#endif // SCORE_EVALUATION_CONCURRENCY_ISSUES_H
Loading
Loading