sproto bugfix

This commit is contained in:
Cloud Wu
2018-01-23 11:24:44 +08:00
parent bbf46f935a
commit 04f4004934
2 changed files with 33 additions and 28 deletions

View File

@@ -2,6 +2,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <math.h>
#include "msvcint.h" #include "msvcint.h"
#include "lua.h" #include "lua.h"
@@ -172,7 +173,7 @@ encode(const struct sproto_arg *args) {
// It's decimal. // It's decimal.
lua_Number vn = lua_tonumber(L, -1); lua_Number vn = lua_tonumber(L, -1);
// use 64bit integer for 32bit architecture. // use 64bit integer for 32bit architecture.
v = (int64_t)(vn * args->extra + 0.5); v = (int64_t)(round(vn * args->extra));
} else { } else {
v = lua_tointegerx(L, -1, &isnum); v = lua_tointegerx(L, -1, &isnum);
if(!isnum) { if(!isnum) {

View File

@@ -11,6 +11,8 @@
#define SIZEOF_LENGTH 4 #define SIZEOF_LENGTH 4
#define SIZEOF_HEADER 2 #define SIZEOF_HEADER 2
#define SIZEOF_FIELD 2 #define SIZEOF_FIELD 2
#define SIZEOF_INT64 ((int)sizeof(uint64_t))
#define SIZEOF_INT32 ((int)sizeof(uint32_t))
struct field { struct field {
int tag; int tag;
@@ -758,7 +760,7 @@ encode_integer_array(sproto_callback cb, struct sproto_arg *args, uint8_t *buffe
return NULL; return NULL;
buffer++; buffer++;
size--; size--;
intlen = sizeof(uint32_t); intlen = SIZEOF_INT32;
index = 1; index = 1;
*noarray = 0; *noarray = 0;
@@ -781,36 +783,38 @@ encode_integer_array(sproto_callback cb, struct sproto_arg *args, uint8_t *buffe
} }
return NULL; // sz == SPROTO_CB_ERROR return NULL; // sz == SPROTO_CB_ERROR
} }
if (size < sizeof(uint64_t)) // notice: sizeof(uint64_t) is size_t (unsigned) , size may be negative. See issue #75
// so use MACRO SIZOF_INT64 instead
if (size < SIZEOF_INT64)
return NULL; return NULL;
if (sz == sizeof(uint32_t)) { if (sz == SIZEOF_INT32) {
uint32_t v = u.u32; uint32_t v = u.u32;
buffer[0] = v & 0xff; buffer[0] = v & 0xff;
buffer[1] = (v >> 8) & 0xff; buffer[1] = (v >> 8) & 0xff;
buffer[2] = (v >> 16) & 0xff; buffer[2] = (v >> 16) & 0xff;
buffer[3] = (v >> 24) & 0xff; buffer[3] = (v >> 24) & 0xff;
if (intlen == sizeof(uint64_t)) { if (intlen == SIZEOF_INT64) {
uint32_to_uint64(v & 0x80000000, buffer); uint32_to_uint64(v & 0x80000000, buffer);
} }
} else { } else {
uint64_t v; uint64_t v;
if (sz != sizeof(uint64_t)) if (sz != SIZEOF_INT64)
return NULL; return NULL;
if (intlen == sizeof(uint32_t)) { if (intlen == SIZEOF_INT32) {
int i; int i;
// rearrange // rearrange
size -= (index-1) * sizeof(uint32_t); size -= (index-1) * SIZEOF_INT32;
if (size < sizeof(uint64_t)) if (size < SIZEOF_INT64)
return NULL; return NULL;
buffer += (index-1) * sizeof(uint32_t); buffer += (index-1) * SIZEOF_INT32;
for (i=index-2;i>=0;i--) { for (i=index-2;i>=0;i--) {
int negative; int negative;
memcpy(header+1+i*sizeof(uint64_t), header+1+i*sizeof(uint32_t), sizeof(uint32_t)); memcpy(header+1+i*SIZEOF_INT64, header+1+i*SIZEOF_INT32, SIZEOF_INT32);
negative = header[1+i*sizeof(uint64_t)+3] & 0x80; negative = header[1+i*SIZEOF_INT64+3] & 0x80;
uint32_to_uint64(negative, header+1+i*sizeof(uint64_t)); uint32_to_uint64(negative, header+1+i*SIZEOF_INT64);
} }
intlen = sizeof(uint64_t); intlen = SIZEOF_INT64;
} }
v = u.u64; v = u.u64;
@@ -956,14 +960,14 @@ sproto_encode(const struct sproto_type *st, void * buffer, int size, sproto_call
return 0; return 0;
return -1; // sz == SPROTO_CB_ERROR return -1; // sz == SPROTO_CB_ERROR
} }
if (sz == sizeof(uint32_t)) { if (sz == SIZEOF_INT32) {
if (u.u32 < 0x7fff) { if (u.u32 < 0x7fff) {
value = (u.u32+1) * 2; value = (u.u32+1) * 2;
sz = 2; // sz can be any number > 0 sz = 2; // sz can be any number > 0
} else { } else {
sz = encode_integer(u.u32, data, size); sz = encode_integer(u.u32, data, size);
} }
} else if (sz == sizeof(uint64_t)) { } else if (sz == SIZEOF_INT64) {
sz= encode_uint64(u.u64, data, size); sz= encode_uint64(u.u64, data, size);
} else { } else {
return -1; return -1;
@@ -1066,22 +1070,22 @@ decode_array(sproto_callback cb, struct sproto_arg *args, uint8_t * stream) {
int len = *stream; int len = *stream;
++stream; ++stream;
--sz; --sz;
if (len == sizeof(uint32_t)) { if (len == SIZEOF_INT32) {
if (sz % sizeof(uint32_t) != 0) if (sz % SIZEOF_INT32 != 0)
return -1; return -1;
for (i=0;i<sz/sizeof(uint32_t);i++) { for (i=0;i<sz/SIZEOF_INT32;i++) {
uint64_t value = expand64(todword(stream + i*sizeof(uint32_t))); uint64_t value = expand64(todword(stream + i*SIZEOF_INT32));
args->index = i+1; args->index = i+1;
args->value = &value; args->value = &value;
args->length = sizeof(value); args->length = sizeof(value);
cb(args); cb(args);
} }
} else if (len == sizeof(uint64_t)) { } else if (len == SIZEOF_INT64) {
if (sz % sizeof(uint64_t) != 0) if (sz % SIZEOF_INT64 != 0)
return -1; return -1;
for (i=0;i<sz/sizeof(uint64_t);i++) { for (i=0;i<sz/SIZEOF_INT64;i++) {
uint64_t low = todword(stream + i*sizeof(uint64_t)); uint64_t low = todword(stream + i*SIZEOF_INT64);
uint64_t hi = todword(stream + i*sizeof(uint64_t) + sizeof(uint32_t)); uint64_t hi = todword(stream + i*SIZEOF_INT64 + SIZEOF_INT32);
uint64_t value = low | hi << 32; uint64_t value = low | hi << 32;
args->index = i+1; args->index = i+1;
args->value = &value; args->value = &value;
@@ -1175,16 +1179,16 @@ sproto_decode(const struct sproto_type *st, const void * data, int size, sproto_
switch (f->type) { switch (f->type) {
case SPROTO_TINTEGER: { case SPROTO_TINTEGER: {
uint32_t sz = todword(currentdata); uint32_t sz = todword(currentdata);
if (sz == sizeof(uint32_t)) { if (sz == SIZEOF_INT32) {
uint64_t v = expand64(todword(currentdata + SIZEOF_LENGTH)); uint64_t v = expand64(todword(currentdata + SIZEOF_LENGTH));
args.value = &v; args.value = &v;
args.length = sizeof(v); args.length = sizeof(v);
cb(&args); cb(&args);
} else if (sz != sizeof(uint64_t)) { } else if (sz != SIZEOF_INT64) {
return -1; return -1;
} else { } else {
uint32_t low = todword(currentdata + SIZEOF_LENGTH); uint32_t low = todword(currentdata + SIZEOF_LENGTH);
uint32_t hi = todword(currentdata + SIZEOF_LENGTH + sizeof(uint32_t)); uint32_t hi = todword(currentdata + SIZEOF_LENGTH + SIZEOF_INT32);
uint64_t v = (uint64_t)low | (uint64_t) hi << 32; uint64_t v = (uint64_t)low | (uint64_t) hi << 32;
args.value = &v; args.value = &v;
args.length = sizeof(v); args.length = sizeof(v);