kingbes/phpc

写更安全的ffi应用

Maintainers

Package info

github.com/KingBes/phpc

pkg:composer/kingbes/phpc

Transparency log

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.0.2 2026-07-20 07:04 UTC

This package is auto-updated.

Last update: 2026-07-20 07:09:39 UTC


README

概述

kingbes/phpc 是一个为 PHP FFI 扩展提供安全防护层的轻量级库。原生 FFI 直接操作 C 内存,容易出现空指针解引用、缓冲区越界、内存泄漏、类型转换错误等问题。本库通过 RAII 包装、白名单加载、边界检查、内存追踪等手段,让 FFI 编码更安全、更省心。

设计原则:功能上不信任 phper,所有公开方法对入参做防御性校验,把错误拦截在 PHP 层而非 C 层(C 层错误往往直接导致进程崩溃)。

  • 命名空间:Kingbes\Phpc
  • 要求:PHP >= 8.2,启用 ext-ffi
  • 许可:MIT

安装

通过 Composer 安装:

composer require kingbes/phpc

最小示例

以下示例加载 libc,调用 strlen 并用 CData::owned 包装器自动释放返回的内存:

<?php
require __DIR__ . '/vendor/autoload.php';

use Kingbes\Phpc\Library;
use Kingbes\Phpc\CData;
use Kingbes\Phpc\SafeCall;
use Kingbes\Phpc\Memory;

$ffi = Library::load('libc', 'int strlen(const char*); void* malloc(size_t); void free(void*);');

// 用 CData::owned 包装 malloc 返回的指针,析构自动 FFI::free
$buf = $ffi->malloc(16);
$wrapped = CData::owned($buf);

// 安全地填充 C 字符串
Memory::copy($wrapped->raw(), 'hello', 5);
$wrapped->raw()[5] = "\0";

// 安全调用 strlen
$len = SafeCall::invoke($ffi, 'strlen', [$wrapped->raw()]);
echo $len; // 5

// 即使忘记 release,析构也会自动 free
$wrapped->release();

更简洁的入口可通过门面类 Kingbes\Phpc\Phpc 完成:

use Kingbes\Phpc\Phpc;

$ffi = Phpc::load('libc', 'int strlen(const char*);');
echo Phpc::call($ffi, 'strlen', [Phpc::toString('hello')]);

组件列表与导航

组件 文档 职责
CData 包装器 Kingbes\Phpc\CData cdata.md RAII 自动释放(owned/external/borrowed 三态)
Pointer 守卫 Kingbes\Phpc\Pointer pointer.md 空指针校验、负数 offset 拦截、可选 max 边界校验
Buffer 守卫 Kingbes\Phpc\Buffer buffer.md 数组类型校验、容量交叉校验、索引越界保护
MemoryTracker Kingbes\Phpc\MemoryTracker memory-tracker.md 内存泄漏检测
Library 加载 Kingbes\Phpc\Library library.md 库名格式校验、白名单管理、文件存在性校验
TypeCast Kingbes\Phpc\TypeCast typecast.md PHP 与 C 类型互转、范围校验
SafeCall Kingbes\Phpc\SafeCall safecall.md C 标识符校验、函数调用守卫
Struct Kingbes\Phpc\Struct struct.md structType 校验、字段读写保护
Memory Kingbes\Phpc\Memory memory.md memcpy/memset/memcmp + 数组越界写校验
门面 Kingbes\Phpc\Phpc - 统一便捷入口

异常体系

所有库内异常均继承自 Kingbes\Phpc\Exception\SafetyException(其本身继承 \Exception),可一次性捕获:

use Kingbes\Phpc\Exception\SafetyException;

try {
    // 任意 Phpc 调用
} catch (SafetyException $e) {
    // 统一处理
}

具体异常类型:

  • NullPointerException - 空指针断言/解引用、expectNotNull 返回空指针
  • BufferOverflowException - Buffer::get/set 越界、Pointer::deref 提供了 $max 且 offset 越界
  • MemoryLeakException - MemoryTracker::assertNoLeaks 检测到泄漏
  • TypeMismatchException - Struct::get/set 字段不存在或类型不匹配
  • LibraryNotPermittedException - 库名格式非法、库未在白名单、头文件内容为空、文件不存在
  • CastException - TypeCast::toInt 类型不支持或值越界、cast 收到空 cType
  • CallException - SafeCall::invoke 函数名非法、函数不存在、expectZero 返回非 0

部分方法还会抛原生异常:

  • \InvalidArgumentException - Pointer::deref 收到负数 offset/max、Memory::set 的 value 越界

示例导览

examples/ 目录下提供 19 个可运行示例,覆盖每个组件的常见用法与异常路径,并包含三个跨平台 GUI 示例:

编号 文件 主题
01 01_cdata.php CData RAII 包装器(owned/external/borrowed)
02 02_pointer.php Pointer 空指针校验与安全解引用
03 03_buffer.php Buffer 数组越界保护
04 04_memory_tracker.php MemoryTracker 泄漏检测
05 05_typecast.php TypeCast 类型互转与范围校验
06 06_safecall.php SafeCall C 函数调用守卫
07 07_struct.php Struct 结构体字段读写
08 08_memory.php Memory memcpy/memset/memcmp
09 09_library.php Library 白名单加载
10 10_facade.php Phpc 门面统一入口
11 11_safety_checks.php 安全校验综合演示
12 12_advanced_struct.php Struct 高级用法(嵌套/数组字段/external)
13 13_exceptions.php 所有异常类型演示
14 14_realworld_string.php 真实场景字符串处理
15 15_hardening.php 新增安全加固校验演示
16 16_win32_gui.php Windows GUI(user32.dll + PHP 闭包作为窗口过程)
17 17_linux_x11_gui.php Linux X11 GUI(libX11 + 事件循环)
18 18_macos_cocoa_gui.php macOS Cocoa GUI(ObjC runtime + objc_msgSend)
19 19_linux_gtk_gui.php Linux GTK3 GUI(libgtk-3 + PHP 闭包作为信号回调)

跨平台示例会在不匹配的操作系统上自动跳过。运行所有示例的回归测试:

php -d ffi.enable=true -f tests/run_examples.php

后续阅读

建议按以下顺序了解各组件:

  1. Library 加载 - 加载 FFI 库的入口
  2. CData 包装器 - 掌握 RAII 模式
  3. Pointer 守卫 - 处理指针安全
  4. TypeCast - PHP/C 类型互转
  5. SafeCall - 调用 C 函数
  6. Struct - 操作结构体
  7. Buffer 守卫 - 安全数组访问
  8. Memory - 内存操作
  9. MemoryTracker - 泄漏检测