protocolbuffers / protocolbuffers/protobuf-javascript

JavaScript Bug - deserializeBinary uint64 field to a unsafe int and not correct number

Open
#67 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug javascript triaged
Dominant language
JavaScript
Stars
471
Forks
91
Avg merge
3h 57m
Merged PRs (30d)
2

Description

I use protoc-3.6.0-osx-x86_64 to convert xx.proto to xx_pb.js and npm install google-protobuf(^3.6.0)

InitConnect.proto

syntax = "proto2";
package InitConnect;

import "Common.proto";

message C2S
{
	required int32 clientVer = 1; //客户端版本号,clientVer = "."以前的数 * 100 + "."以后的,举例:1.1版本的clientVer为1 * 100 + 1 = 101,2.21版本为2 * 100 + 21 = 221
	required string clientID = 2; //客户端唯一标识,无生具体生成规则,客户端自己保证唯一性即可
	optional bool recvNotify = 3; //此连接是否接收市场状态、交易需要重新解锁等等事件通知,true代表接收,FutuOpenD就会向此连接推送这些通知,反之false代表不接收不推送
}

message S2C
{
	required int32 serverVer = 1; //FutuOpenD的版本号
	required uint64 loginUserID = 2; //FutuOpenD登陆的牛牛用户ID
	required uint64 connID = 3; //此连接的连接ID,连接的唯一标识
	required string connAESKey = 4; //此连接后续AES加密通信的Key,固定为16字节长字符串
	required int32 keepAliveInterval = 5; //心跳保活间隔
}

message Request
{
	required C2S c2s = 1;
}

message Response
{
	required int32 retType = 1 [default = -400]; //返回结果,参见Common.RetType的枚举定义
	optional string retMsg = 2; //返回结果描述
	optional int32 errCode = 3; //错误码,客户端一般通过retType和retMsg来判断结果和详情,errCode只做日志记录,仅在个别协议失败时对账用
	
	optional S2C s2c = 4;
}

I convert InitConnect.proto to InitConnect_pb.js And Import it to node.js code

const InitConnectMessage = require("InitConnect_pb.js")

//I get PackageBody_Buffer from net, then deserializeBinary

let ResponseBody_Object = InitConnectMessage.Response.deserializeBinary(PackageBody_Buffer);
ResponseBody_Object = ResponseBody_Object.toObject();
console.log(ResponseBody_Object)

The log is :

{ rettype: 0,
  retmsg: '',
  errcode: 0,
  s2c:
   { serverver: 100,
     loginuserid: 2131552,
     connid: 167141872653707230,
     connaeskey: 'D7279ECAA5CF51E8',
     keepaliveinterval: 10 } } 

As the result, the deserialized connid is 167141872653707230, more than js Number.MAX_SAFE_INTEGER// → 9_007_199_254_740_991
Moreover the deserialized connid is not equal to the original connid!

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the uint64 fields in InitConnect.proto and trace the generated InitConnect_pb.js through Response.deserializeBinary() and toObject(). Determine how values beyond Number.MAX_SAFE_INTEGER should be represented, then verify that connID round-trips without changing the original value.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
backend-api-design
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.