Skip to content

bug: toArrayLike() crashes with zero-valued BigNumberΒ #80

@gupta-ji6

Description

@gupta-ji6

Summary

Hi! πŸ‘‹

Firstly, thanks for your work on this project! πŸ™‚

The toArrayLike() method in react-native-bignumber crashes when called on a BigNumber representing zero. This occurs because the method creates a 0-length buffer and passes it to native code, which causes an immediate native crash.

Environment

  • react-native-bignumber: 0.2.3
  • Platform: React Native (iOS/Android) 0.74.7
  • Impact: Critical - Native app crash

Problem Description

When toArrayLike() is called on a BigNumber with value 0:

  1. this.byteLength() returns 0
  2. outLen becomes 0
  3. A 0-length buffer is created: new ArrayType(0)
  4. The 0-length buffer is passed to native.toArrayLike.call()
  5. Native code crashes attempting to work with empty buffer

Code Analysis

Current Implementation (Crashing)

Refer -

toArrayLike<T extends (len: number) => { buffer: ArrayBuffer }>(

toArrayLike(arrayLike, endian?, len?) {
  const outLen = len != null ? len : this.byteLength();  // ❌ Can be 0
  
  const res = new (arrayLike as any)(outLen);  // ❌ Creates 0-length buffer
  
  native.toArrayLike.call(
    this.internalBigNum,
    res.buffer,  // ❌ 0-length buffer crashes native code
    endian === 'le',
    len || -1
  );
  return res;
}

Standard bn.js Implementation (Working)

Refer - https://github.com/indutny/bn.js/blob/6db7c3818569423b94ebcf2bdff90fcfb9c47f6d/lib/bn.js#L573

BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) {
  var byteLength = this.byteLength();
  var reqLength = length || Math.max(1, byteLength);  // βœ… Ensures minimum 1 byte
  
  var res = allocate(ArrayType, reqLength);
  // ... pure JS implementation (no native crashes)
  return res;
};

Reproduction Steps

Minimal Reproduction

import { BN } from 'react-native-bignumber';

// Create a zero-valued BigNumber
const zeroBN = new BN(0);

// This should crash the app
const buffer = zeroBN.toArrayLike(Buffer);  // πŸ’₯ CRASH

Real-world Scenario (Solana Web3.js)

This issue was discovered when using Solana's web3.js library @solana/[email protected] in React Native. It uses bn.js but we have polyfilled it with react-native-bignumber

Refer - https://github.com/solana-foundation/solana-web3.js/blob/16f145d4ba5542488e22c0b71d539c4e36ae65f5/src/publickey.ts#L123

  toBuffer(): Buffer {
    const b = this._bn.toArrayLike(Buffer); // toArrayLike called here
    if (b.length === PUBLIC_KEY_LENGTH) {
      return b;
    }

    const zeroPad = Buffer.alloc(32);
    b.copy(zeroPad, 32 - b.length);
    return zeroPad;
  }

Impact: This makes Solana SOL transfers failures in React Native apps, as the Solana System Program ID 11111111111111111111111111111111 is required for all SOL transfer transactions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions