Skip to content

Commit

Permalink
🔧 fix bad case when cow hit sso
Browse files Browse the repository at this point in the history
  • Loading branch information
orca-zhang committed Jan 28, 2019
1 parent 3cfb16a commit cf2be85
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 5 deletions.
6 changes: 6 additions & 0 deletions ut/ut_xpjson.h
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,12 @@ TEST(ut_xpjson, read)
// case 9 end with backslash in key
in = "{\"a\\";
EXPECT_THROW(JSON::Reader::read(v, in.c_str(), in.length()), std::logic_error);

// case 10 bad cow case when hit sso(1/5/9/13 bytes)
JSON::Value v2("yyyyy");
v = v2; // incorrect treat as cow when cow(sso_len highest bit) is true
*const_cast<char*>(v2.c_str()) = 'z';
ASSERT_TRUE(v.s() == "yyyyy");
}
catch(std::exception &e) {
printf("Error : %s.", e.what());
Expand Down
6 changes: 6 additions & 0 deletions ut/ut_xpjsonW.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,12 @@ TEST(ut_xpjsonW, read)
// case 9 end with backslash in key
in = L"{\"a\\";
EXPECT_THROW(JSON::ReaderW::read(v, in.c_str(), in.length()), std::logic_error);

// case 10 bad cow case when hit sso(1/5 bytes if sizof(wchar_t) is 2; 1 byte if sizof(wchar_t) is 4)
JSON::ValueW v2(L"y");
v = v2; // incorrect treat as cow when cow(sso_len highest bit) is true
*const_cast<wchar_t*>(v2.c_str()) = 'z';
ASSERT_TRUE(v.s() == L"y");
}
catch(std::exception &e) {
printf("Error : %s.", e.what());
Expand Down
10 changes: 5 additions & 5 deletions xpjson.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -793,10 +793,10 @@ template<> inline void to_string<type, char_t>(type v, JSON_TSTRING(char_t)& out

protected:
unsigned char _type : 3;
mutable bool _sso : 1; // small string optimization
mutable bool _sso : 1; // small-string-optimization
union {
struct { // not sso
mutable bool _cow : 1; // used for direct memory access string
mutable bool _cow : 1; // used for copy-on-write string
bool _e : 1; // used for string, indicates needs to be escaped or encoded.
char : 2; // reserved
};
Expand Down Expand Up @@ -937,7 +937,7 @@ namespace JSON
case STRING:
_sso = true;
_sso_len = 0;
assign(v.c_str(), v.length(), v._e, v._cow);
assign(v.c_str(), v.length(), v._e, !v._sso && v._cow);
break;
case OBJECT: _o = new ObjectT<char_t>(*v._o); break;
case ARRAY: _a = new ArrayT<char_t>(*v._a); break;
Expand Down Expand Up @@ -1025,7 +1025,7 @@ namespace JSON
case INTEGER: _i = v._i; break;
case FLOAT: _f = v._f; break;
case STRING:
assign(v.c_str(), v.length(), v._e, v._cow);
assign(v.c_str(), v.length(), v._e, !v._sso && v._cow);
break;
case OBJECT: *_o = *v._o; break;
case ARRAY: *_a = *v._a; break;
Expand All @@ -1050,7 +1050,7 @@ namespace JSON
_e = v._e;
}
else {
assign(v.c_str(), v.length(), v._e, v._cow);
assign(v.c_str(), v.length(), v._e, !v._sso && v._cow);
}
break;
case OBJECT: swap(_o, v._o); break;
Expand Down

0 comments on commit cf2be85

Please sign in to comment.