uni-app App模式下,字符串首字节为0x00时,造成日志输出宕住

uni-app App模式下,字符串首字节为0x00时,造成日志输出宕住

开发环境 版本号 项目创建方式
Mac 14.2.1 HBuilderX
iOS iOS 14

产品分类:uniapp/App

PC开发环境操作系统:Mac

HBuilderX类型:正式

HBuilderX版本号:3.96

手机系统:iOS

手机系统版本号:iOS 14

手机厂商:苹果

手机机型:iPhone6

页面类型:vue

vue版本:vue2

打包方式:云端

操作步骤:

let str = '\x00\x01\x03';  
console.log('字符串是',  str);  
console.log('字符串是' + str);

预期结果:

输出日志

实际结果:

程序hang住

bug描述: 此BUG和具体App无关,预测是console.log日志族在输出ascii string时,存在BUG。

如下面的代码,在string的第一个字节为0x00时,程序不提示异常,进入到等待状态,后续代码不执行。 或者也可以用 let str = ‘\x00\x01\x03’;这种方式,用console.log进行日志输出,可重现。

try {  
  let str = '';  
  console.log('1.str is:', str);  
  str = 0x00;  
  console.log('2.str with value 0x00 is:', str);  
  str = '\0';  
  console.log('3.str with value slash zero is:' + str);  
} catch (e) {  
  console.warn("字符串的日志输出错误", e)  
}

更多关于uni-app App模式下,字符串首字节为0x00时,造成日志输出宕住的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

目前只有iOS的App模式下存在此问题,同样的代码,在Android的App模式,以及微信和支付宝小程序的Android及iOS均无问题。

更多关于uni-app App模式下,字符串首字节为0x00时,造成日志输出宕住的实战教程也可以访问 https://www.itying.com/category-93-b0.html


非printable的字符串日志输出,这个我们可以屏蔽掉,但是问题的起因在于我们需要向蓝牙下发数据,一个设备的pdu的第一个字节定义必须是0x00,所以发现了这个问题。
屏蔽了日志,我们的程序在iOS的App模式下也是不行,怀疑在处理0x00开始的string,其它地方也存在同样的BUG

uni-app 的 App 模式下,如果字符串的首字节为 0x00(即空字符 \0),可能会导致日志输出时出现异常,甚至导致应用“宕住”(即卡住或崩溃)。这是因为 0x00 在 C/C++ 等底层语言中通常被视为字符串的结束符,而在某些情况下,日志输出函数可能会错误地将其解释为字符串的结束,从而导致未定义的行为。

解决方案

  1. 检查字符串内容
    在处理字符串之前,先检查字符串的内容,确保它不包含 0x00 这样的特殊字符。可以通过遍历字符串来检查每个字符的值。

    function containsNullByte(str) {
        return str.indexOf('\0') !== -1;
    }
    
    if (containsNullByte(myString)) {
        console.error("String contains null byte!");
    }
    
  2. 替换或移除空字符
    如果字符串中包含 0x00,可以将其替换为其他字符或直接移除。

    function removeNullBytes(str) {
        return str.replace(/\0/g, '');
    }
    
    myString = removeNullBytes(myString);
    
  3. 使用 Base64 编码
    如果字符串中包含不可打印的字符(如 0x00),可以将其转换为 Base64 编码后再进行日志输出。

    function encodeBase64(str) {
        return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (match, p1) => {
            return String.fromCharCode('0x' + p1);
        }));
    }
    
    console.log(encodeBase64(myString));
    
  4. 使用 ArrayBuffer 或 TypedArray
    如果你需要处理二进制数据,可以使用 ArrayBufferTypedArray 来存储和操作数据,而不是直接使用字符串。

    let buffer = new ArrayBuffer(10);
    let view = new Uint8Array(buffer);
    
    // 填充数据
    view[0] = 0x00;
    view[1] = 0x01;
    
    // 日志输出时,可以将 ArrayBuffer 转换为十六进制字符串
    function bufferToHex(buffer) {
        return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
    }
    
    console.log(bufferToHex(buffer));
    
  5. 调试和日志输出
    在调试时,可以使用 JSON.stringify 将对象转换为字符串,这样可以避免直接输出包含特殊字符的字符串。

    console.log(JSON.stringify(myObject));
回到顶部