bson check utf8 string

This commit is contained in:
Cloud Wu
2017-02-09 17:26:48 +08:00
parent af6b5609de
commit 2e919505f1

View File

@@ -198,10 +198,50 @@ write_length(struct bson *b, int32_t v, int off) {
b->ptr[off++] = (uv >> 24)&0xff;
}
#define MAXUNICODE 0x10FFFF
static int
utf8_copy(const char *s, char *d, size_t limit) {
static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF};
unsigned int c = s[0];
unsigned int res = 0;
if (limit < 1)
return 0;
d[0] = s[0];
if (c < 0x80) {
return 1;
} else {
int count = 0;
while (c & 0x40) {
int cc = s[++count];
if (limit <= count || (cc & 0xC0) != 0x80)
return 0;
d[count] = s[count];
res = (res << 6) | (cc & 0x3F);
c <<= 1;
}
res |= ((c & 0x7F) << (count * 5));
if (count > 3 || res > MAXUNICODE || res <= limits[count])
return 0;
return count+1;
}
}
static void
write_string(struct bson *b, const char *key, size_t sz) {
write_string(struct bson *b, lua_State *L, const char *key, size_t sz) {
bson_reserve(b,sz+1);
memcpy(b->ptr + b->size, key, sz);
char *dst = (char *)(b->ptr + b->size);
const char *src = key;
size_t n = sz;
while(n > 0) {
int c = utf8_copy(src, dst, n);
if (c == 0) {
luaL_error(L, "Invalid utf8 string");
}
src += c;
dst += c;
n -= c;
}
b->ptr[b->size+sz] = '\0';
b->size+=sz+1;
}
@@ -239,9 +279,9 @@ write_double(struct bson *b, lua_Number d) {
}
static inline void
append_key(struct bson *bs, int type, const char *key, size_t sz) {
append_key(struct bson *bs, lua_State *L, int type, const char *key, size_t sz) {
write_byte(bs, type);
write_string(bs, key, sz);
write_string(bs, L, key, sz);
}
static inline int
@@ -254,15 +294,15 @@ append_number(struct bson *bs, lua_State *L, const char *key, size_t sz) {
if (lua_isinteger(L, -1)) {
int64_t i = lua_tointeger(L, -1);
if (is_32bit(i)) {
append_key(bs, BSON_INT32, key, sz);
append_key(bs, L, BSON_INT32, key, sz);
write_int32(bs, i);
} else {
append_key(bs, BSON_INT64, key, sz);
append_key(bs, L, BSON_INT64, key, sz);
write_int64(bs, i);
}
} else {
lua_Number d = lua_tonumber(L,-1);
append_key(bs, BSON_REAL, key, sz);
append_key(bs, L, BSON_REAL, key, sz);
write_double(bs, d);
}
}
@@ -286,7 +326,7 @@ append_one(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth)
append_number(bs, L, key, sz);
break;
case LUA_TUSERDATA: {
append_key(bs, BSON_DOCUMENT, key, sz);
append_key(bs, L, BSON_DOCUMENT, key, sz);
int32_t * doc = lua_touserdata(L,-1);
int32_t sz = *doc;
bson_reserve(bs,sz);
@@ -299,7 +339,7 @@ append_one(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth)
const char * str = lua_tolstring(L,-1,&len);
if (len > 1 && str[0]==0) {
int subt = (uint8_t)str[1];
append_key(bs, subt, key, sz);
append_key(bs, L, subt, key, sz);
switch(subt) {
case BSON_BINARY:
write_binary(bs, str+2, len-2);
@@ -345,8 +385,8 @@ append_one(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth)
break;
}
}
write_string(bs, str, len-i-1);
write_string(bs, str + len-i, i);
write_string(bs, L, str, len-i-1);
write_string(bs, L, str + len-i, i);
break;
}
case BSON_MINKEY:
@@ -359,9 +399,9 @@ append_one(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth)
} else {
size_t len;
const char * str = lua_tolstring(L,-1,&len);
append_key(bs, BSON_STRING, key, sz);
append_key(bs, L, BSON_STRING, key, sz);
int off = reserve_length(bs);
write_string(bs, str, len);
write_string(bs, L, str, len);
write_length(bs, len+1, off);
}
break;
@@ -370,7 +410,7 @@ append_one(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth)
append_table(bs, L, key, sz, depth+1);
break;
case LUA_TBOOLEAN:
append_key(bs, BSON_BOOLEAN, key, sz);
append_key(bs, L, BSON_BOOLEAN, key, sz);
write_byte(bs, lua_toboolean(L,-1));
break;
default:
@@ -491,16 +531,16 @@ append_table(struct bson *bs, lua_State *L, const char *key, size_t sz, int dept
}
size_t len = lua_tointeger(L, -1);
lua_pop(L, 1);
append_key(bs, BSON_ARRAY, key, sz);
append_key(bs, L, BSON_ARRAY, key, sz);
pack_array(L, bs, depth, len);
} else if (luaL_getmetafield(L, -1, "__pairs") != LUA_TNIL) {
append_key(bs, BSON_DOCUMENT, key, sz);
append_key(bs, L, BSON_DOCUMENT, key, sz);
pack_meta_dict(L, bs, depth);
} else if (is_rawarray(L)) {
append_key(bs, BSON_ARRAY, key, sz);
append_key(bs, L, BSON_ARRAY, key, sz);
pack_array(L, bs, depth, lua_rawlen(L, -1));
} else {
append_key(bs, BSON_DOCUMENT, key, sz);
append_key(bs, L, BSON_DOCUMENT, key, sz);
pack_simple_dict(L, bs, depth);
}
}