byte10
V2EX  ›  问与答

大家是怎么判断 AI 写的代码是正确的?有验收标准吗?

  •  
  •   byte10 · 1h 8m ago · 33 views

    如题

    我最近也是在用 AI 写 nodejs ,但是遇到一些问题,先举例子。

    1 、第一个 CRC32 的函数实现

    function crc32(buf, init = 0xffffffff) {
      // 预生成表(全局只初始化一次)
      if (!crc32.table) {
        const table = new Uint32Array(256)
        for (let i = 0; i < 256; i++) {
          let crc = i
          for (let j = 0; j < 8; j++) {
            crc = (crc >>> 1) ^ (crc & 1 ? 0xedb88320 : 0)
          }
          table[i] = crc >>> 0
        }
        crc32.table = table
      }
      let crc = init >>> 0
      const tbl = crc32.table
      for (const byte of buf) {
        crc = (crc >>> 8) ^ tbl[(crc ^ byte) & 0xff]
      }
      // 最终异或输出
      return (crc ^ 0xffffffff) >>> 0
    }
    
    

    这个代码我是从豆包那边拿到的,文心和 deepseek 都有查询过,大差不差吧,豆包实现的代码确实比较简洁一些。代码量虽然不多,如果要去审核也要花点时间,所以我就用在线的网页版本 CRC32 去做了几次对照验证,我感觉这样肯定是不严谨的。。

    2 、AES-CTR 的 nonce 增加的计算

    incrementIV2(nonce, blocks) {
        const result = new Uint8Array(nonce)
        let carry = blocks
        // i 从最低字节(15)到高字节(8)
        for (let i = 15; i >= 8 && carry > 0; i--) {
          // 这里 2^53-1 + result[i] 会出现精度问题
          const sum = result[i] + carry
          result[i] = sum & 0xff
          carry = Math.floor(sum / 256)
        }
        // carry>0 代表 uint64 溢出,CTR 不安全
        if (carry > 0) throw new Error('CTR counter uint64 overflow')
        return result
      }
    

    因为要分片加密,所以要拿到 blocks 的数量去获取当前位置的 nonce ,关于这个值的计算,不同 ai 给出的实现方法都略有差异。

    // claude Code 的代码
    incrementIV3(nonce, blocks) {
        const result = new Uint8Array(nonce)
        let carry = blocks
        for (let index = 15; index >= 8 && carry > 0; index--) {
          const sum = result[index] + (carry % 256)
          result[index] = sum & 0xff
          carry = Math.floor(carry / 256) + Math.floor(sum / 256)
        }
        if (carry > 0) {
          throw new Error('AES‑CTR uint64 counter overflow, insecure')
        }
        return result
      }
    

    上面那些都是我基本验证过的,还有一些是错的代码例子,豆包第一次给是:比如 carry = sum >>> 8 ,这种超过 2^32 就会出问题。我真的遇到太多的问题了。

    下面的代码之前给出的是不带 bytes >>> 0 ,就会出现负数,就出 bug 。

    // 小端序,转 32 位数字
    function toUInt32LE(bytes) {
       // bytes >>> 0 避免负数
       return (bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24)) >>> 0;
    }
    

    最后

    后面我就在群里吐槽过这样的问题,有一个老哥就说了他的理论:

    • 1 、测试用例,测试边界你要描述清楚啊
    • 2 、你的文档和测试用例不够。
    • 3 、交付物验收标准就是你要描述的。

    就拿那个 aes-ctr 的 nonce 计算,怎么描述测试用例?问题是我自己都无法知道它是对的还是错的,虽然就几行代码,花几分钟也能吃下来(其实几个实现的版本我没贴上)。但是我很难证明它是对的,或者还有什么坑没填。CRC32 我可用在线的网页去验证,甚至用内置的 API 去验证,aes-ctr 是 nodejs 没有内置 counter 增加的 API 的,所以能用文件分片去解密对照验证。

    还有其他的案例,比如 CJK 字符编码,有一个隐藏的 bug ,也许 90%的测试用例都无法测试出来,我是硬生生把里面的代码走一遍才发现的,虽然 bug 也很明显,但是不走读代码几乎测试不出来,因为字符串要满足字节长度是 14 的倍数,以及最后一个字节是 1-13 才出现 bug 。

    AI 提供的思路确实很不错,给的代码也基本符合要求,但经常会有些问题,关键是这些问题不好发现。我没尝试过整体项目用 AI 写,也许业务层面上,AI 会有不错的表现,或者说其他语言下,AI 能写的更好。

    sduoduo233
        1
    sduoduo233  
       44 mins ago via Android
    拿代码多问几个 ai ,专家会诊
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2969 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 07:52 · PVG 15:52 · LAX 00:52 · JFK 03:52
    ♥ Do have faith in what you're doing.