Skip to content

cc code review #225

@xiaods

Description

@xiaods

核心问题 1: 内存管理中的竞争条件 (Race Condition) - data.hpp

位置: /Users/xiaods/Documents/code/pipy/src/data.hpp:363-378

问题描述:
在 Data::Chunk 结构中,引用计数使用了原子操作,但在 release() 方法中存在潜在的竞争条件:

struct Chunk : public Pooled {
std::atomic retain_count;

  void retain() { retain_count.fetch_add(1, std::memory_order_relaxed); }
  void release() {
      if (retain_count.fetch_sub(1, std::memory_order_acq_rel) == 1)
          delete this;
  }

}

风险:

  1. 内存序问题: retain() 使用 memory_order_relaxed,这意味着其他线程可能看不到最新的引用计数
  2. 析构竞争: 如果两个线程同时调用 release(),可能导致双重删除
  3. Producer 计数器不同步: m_producer->increase()/decrease() 在构造/析构时调用,但引用计数操作使用的是 relaxed ordering

建议修复:

  • retain() 应使用 memory_order_acquire 或至少 memory_order_release
  • 在 release() 中检查返回值是否为 1 之前,应该使用更强的内存序保证
  • 考虑使用 std::shared_ptr 或更安全的引用计数机制

核心问题 2: TLS 证书验证回调中的异常处理缺失 - tls.cpp

位置: /Users/xiaods/Documents/code/pipy/src/filters/tls.cpp:412-423 和 /Users/xiaods/Documents/code/pipy/src/filters/tls.cpp:540-557

问题描述:
在 TLS 会话的证书验证和证书使用过程中,缺少对 OpenSSL API 调用返回值的完整检查:

// 540-557: 缺少错误检查
SSL_use_PrivateKey(m_ssl, key.ascrypto::PrivateKey()->pkey()); // 没有检查返回值

if (cert.iscrypto::Certificate()) {
SSL_use_certificate(m_ssl, cert.ascrypto::Certificate()->x509()); // 没有检查返回值
} else if (cert.iscrypto::CertificateChain()) {
auto chain = cert.ascrypto::CertificateChain();
if (chain->size() < 1) {
m_filter->error("empty certificate chain");
} else {
SSL_use_certificate(m_ssl, chain->x509(0)); // 没有检查返回值
for (int i = 1; i < chain->size(); i++) {
SSL_add1_chain_cert(m_ssl, chain->x509(i)); // 没有检查返回值
}
}
}

风险:

  1. 静默失败: SSL_use_PrivateKey、SSL_use_certificate、SSL_add1_chain_cert 失败时不会报告错误
  2. 不匹配的密钥对: 私钥和证书不匹配时,TLS 握手会在稍后阶段失败,难以调试
  3. 安全隐患: 可能使用错误的证书进行 TLS 连接,导致中间人攻击风险
  4. NTLS 分支同样问题: 在 PIPY_USE_NTLS 编译选项下,所有 SSL_use_sign/enc_* API 都缺少错误检查

建议修复:
if (SSL_use_PrivateKey(m_ssl, key.ascrypto::PrivateKey()->pkey()) != 1) {
throw_error(); // 或记录错误并返回
}
// 其他 SSL API 调用也应该添加类似检查


核心问题 3: Connect 过滤器中的状态回调异常处理不完整 - connect.cpp

位置: /Users/xiaods/Documents/code/pipy/src/filters/connect.cpp:183-189

问题描述:
虽然最近的提交 (a1468e4) 修复了 onState 回调异常时不应继续连接的问题,但实现仍然不完整:

if (options.on_state_f) {
pjs::Refpjs::Function f = options.on_state_f;
options.on_state_changed = [=](Outbound *ob) {
pjs::Value arg(ob), ret;
return Filter::callback(f, 1, &arg, ret); // callback 返回 bool
};
}

结合 outbound.cpp:123-131:
bool Outbound::state(State state) {
if (m_state != state) {
m_state = state;
if (const auto &f = m_options.on_state_changed) {
return f(this); // 如果返回 false,状态已经改变但没有回滚
}
}
return true;
}

风险:

  1. 状态不一致: state() 方法先修改状态,然后调用回调。如果回调返回 false,状态已经改变但没有恢复
  2. 资源泄漏: 在 outbound.cpp:277 和其他地方调用 state() 后,如果返回 false,socket 已经打开但没有正确清理
  3. 不完整的错误传播: 回调失败时,某些代码路径没有检查返回值 (如 outbound.cpp:427-428)

建议修复:

  1. 在 Outbound::state() 中,应该先调用回调,只有返回 true 时才修改状态
  2. 在所有调用 state() 的地方都检查返回值并进行适当的清理
  3. 添加事务性状态管理,失败时能够回滚到之前的状态

总结

这三个问题都是关键核心代码中的安全和可靠性问题:

  1. 问题 1 可能导致内存损坏和崩溃
  2. 问题 2 可能导致 TLS 安全漏洞
  3. 问题 3 可能导致资源泄漏和状态不一致

建议优先修复这些问题,特别是在生产环境使用前

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions