Merge pull request #315 from RomainROCH/codex/fix-semaphore-overflow

fix(libkernel): avoid semaphore count overflow
This commit is contained in:
Dean 2026-10-04 14:01:19 +13:00 committed by GitHub
commit e5676b3f0e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 22 additions and 1 deletions

View File

@ -41,7 +41,7 @@ int APS5_VABI sceKernelSignalSema(KernelSema sem, int count) {
}
std::lock_guard<std::mutex> lock(sem->mutex);
if (sem->tokenCount + count > sem->maxCount) {
if (count > sem->maxCount - sem->tokenCount) {
return SCE_KERNEL_ERROR_EINVAL;
}
sem->tokenCount += count;

View File

@ -1,9 +1,14 @@
#include "SceTypes.hpp"
#include <cstdint>
#include <cstdlib>
#include <limits>
#include <stdexcept>
extern "C" {
int APS5_VABI sceKernelCreateSema(KernelSema*, const char*, std::uint32_t, int, int, void*);
int APS5_VABI sceKernelDeleteSema(KernelSema);
int APS5_VABI sceKernelSignalSema(KernelSema, int);
int APS5_VABI sceKernelPollSema(KernelSema, int);
int APS5_VABI sceKernelCreateEqueue(KernelEqueue* eq, const char* name);
int APS5_VABI sceKernelDeleteEqueue(KernelEqueue eq);
int APS5_VABI sceKernelWaitEqueue(KernelEqueue eq, KernelEvent* ev, int num, int* out, const KernelUseconds* timo);
@ -33,6 +38,22 @@ static constexpr int PRIO_PROTECT = 2;
static void Require(bool value) { if (!value) std::abort(); }
int main() {
constexpr int maximum = std::numeric_limits<int>::max();
KernelSema semaphore = nullptr;
Require(sceKernelCreateSema(&semaphore, "overflow", 1, maximum - 1, maximum, nullptr) == SCE_OK);
Require(sceKernelSignalSema(semaphore, 2) == SCE_KERNEL_ERROR_EINVAL);
Require(sceKernelSignalSema(semaphore, maximum) == SCE_KERNEL_ERROR_EINVAL);
Require(sceKernelPollSema(semaphore, maximum - 1) == SCE_OK);
Require(sceKernelSignalSema(semaphore, maximum) == SCE_OK);
Require(sceKernelSignalSema(semaphore, 1) == SCE_KERNEL_ERROR_EINVAL);
Require(sceKernelPollSema(semaphore, maximum) == SCE_OK);
Require(sceKernelDeleteSema(semaphore) == SCE_OK);
Require(sceKernelCreateSema(&semaphore, "limit", 1, 1, 3, nullptr) == SCE_OK);
Require(sceKernelSignalSema(semaphore, 3) == SCE_KERNEL_ERROR_EINVAL);
Require(sceKernelSignalSema(semaphore, 2) == SCE_OK);
Require(sceKernelPollSema(semaphore, 3) == SCE_OK);
Require(sceKernelDeleteSema(semaphore) == SCE_OK);
KernelEqueue eq = 0;
Require(sceKernelCreateEqueue(&eq, "errors") == SCE_OK);
KernelEvent event{};