parser release has a precondition

This commit is contained in:
Vinnie Falco 2020-09-08 17:42:14 -07:00
parent 3204021a90
commit 24e8e45690
8 changed files with 45 additions and 58 deletions

View File

@ -279,7 +279,7 @@ public:
p.write(s.data(), s.size(), ec); p.write(s.data(), s.size(), ec);
if(! ec) if(! ec)
p.finish(ec); p.finish(ec);
auto jv = p.release(ec); auto jv = p.release();
} }
} }
@ -346,7 +346,7 @@ public:
p.write(s.data(), s.size(), ec); p.write(s.data(), s.size(), ec);
if(! ec) if(! ec)
p.finish(ec); p.finish(ec);
auto jv = p.release(ec); auto jv = p.release();
} }
} }

View File

@ -41,7 +41,7 @@ parse_file( char const* filename )
p.finish( ec ); p.finish( ec );
if( ec ) if( ec )
return nullptr; return nullptr;
return p.release( ec ); return p.release();
} }
void void

View File

@ -13,10 +13,11 @@
using namespace boost::json; using namespace boost::json;
bool bool
fuzz_parser(parse_options popt,string_view sv) fuzz_parser(
parse_options opt,
string_view sv)
{ {
parser p(storage_ptr{}, opt);
parser p(storage_ptr{},popt);
error_code ec; error_code ec;
// This must be called once before parsing every new JSON // This must be called once before parsing every new JSON
@ -31,9 +32,8 @@ fuzz_parser(parse_options popt,string_view sv)
// Take ownership of the resulting value. // Take ownership of the resulting value.
if(! ec) if(! ec)
{ {
value jv = p.release( ec ); value jv = p.release();
if(! ec ) return serialize(jv).size()==42;
return serialize(jv).size()==42;
} }
return false; return false;
} }
@ -46,11 +46,11 @@ LLVMFuzzerTestOneInput(
if(size<1) if(size<1)
return 0; return 0;
parse_options popt; parse_options opt;
popt.allow_comments=!!(data[0]&0x1); opt.allow_comments=!!(data[0]&0x1);
popt.allow_trailing_commas=!!(data[0]&0x2); opt.allow_trailing_commas=!!(data[0]&0x2);
popt.allow_invalid_utf8=!!(data[0]&0x4); opt.allow_invalid_utf8=!!(data[0]&0x4);
popt.max_depth= (data[0]>>3); opt.max_depth= (data[0]>>3);
data+=1; data+=1;
size-=1; size-=1;
@ -61,7 +61,7 @@ LLVMFuzzerTestOneInput(
string_view view{ string_view view{
reinterpret_cast<const char*>( reinterpret_cast<const char*>(
data), size}; data), size};
fuzz_parser(popt,view); fuzz_parser(opt,view);
} }
catch(...) catch(...)
{ {

View File

@ -38,7 +38,7 @@ parse(
p.finish(ec); p.finish(ec);
if(ec) if(ec)
return nullptr; return nullptr;
return p.release(ec); return p.release();
} }
value value

View File

@ -268,12 +268,10 @@ finish(error_code& ec)
value value
parser:: parser::
release(error_code& ec) release()
{ {
if(p_.done()) BOOST_ASSERT(p_.done());
return p_.handler().st.release(); return p_.handler().st.release();
ec = error::incomplete;
return nullptr;
} }
BOOST_JSON_NS_END BOOST_JSON_NS_END

View File

@ -529,30 +529,32 @@ public:
/** Return the parsed JSON as a @ref value. /** Return the parsed JSON as a @ref value.
If @ref done() returns `true`, then the This returns the parsed value.
parsed value is returned. Otherwise,
the error is set to indicate failure. It
is necessary to call @ref reset after calling is necessary to call @ref reset after calling
this function in order to parse another JSON. this function in order to parse another JSON.
Undefined behavior results if the parser is
not done, or if an error occurred during
parsing.
@par Preconditions
@code
this->done() == true
@endcode
@par Complexity @par Complexity
Constant. Constant.
@par Exception Safety @par Exception Safety
Strong guarantee. If an exception occurs, Strong guarantee. If an exception occurs,
the valid operations are @ref reset or the valid operations are @ref reset or
destruction. destruction.
@return The parsed value. Ownership of this @return The parsed value. Ownership of this
value is transferred to the caller. value is transferred to the caller.
@param ec Set to the error, if any occurred.
*/ */
BOOST_JSON_DECL BOOST_JSON_DECL
value value
release(error_code& ec); release();
}; };
BOOST_JSON_NS_END BOOST_JSON_NS_END

View File

@ -70,7 +70,7 @@ public:
if(BOOST_TEST(! ec)) if(BOOST_TEST(! ec))
p.finish(ec); p.finish(ec);
BOOST_TEST(! ec); BOOST_TEST(! ec);
return p.release(ec); return p.release();
} }
void void
@ -144,7 +144,7 @@ public:
if(BOOST_TEST(! ec)) if(BOOST_TEST(! ec))
p.finish(ec); p.finish(ec);
if(BOOST_TEST(! ec)) if(BOOST_TEST(! ec))
f(p.release(ec), po); f(p.release(), po);
} }
} }
} }
@ -302,7 +302,7 @@ public:
p.finish(ec); p.finish(ec);
if(BOOST_TEST(! ec)) if(BOOST_TEST(! ec))
check_round_trip( check_round_trip(
p.release(ec)); p.release());
} }
} }
} }
@ -331,8 +331,7 @@ public:
p.finish(ec); p.finish(ec);
if(! BOOST_TEST(! ec)) if(! BOOST_TEST(! ec))
return 0; return 0;
auto const jv = p.release(ec); auto const jv = p.release();
BOOST_TEST(! ec);
double const d = jv.as_double(); double const d = jv.as_double();
grind_double(s, d); grind_double(s, d);
return d; return d;
@ -773,14 +772,6 @@ public:
p.reset(); p.reset();
} }
// release before done
{
parser p;
error_code ec;
p.release(ec);
BOOST_TEST(ec == error::incomplete);
}
// write(char const*, size_t, error_code&) // write(char const*, size_t, error_code&)
{ {
{ {
@ -930,10 +921,7 @@ R"xx({
if(BOOST_TEST(! ec)) if(BOOST_TEST(! ec))
p.finish(ec); p.finish(ec);
if(BOOST_TEST(! ec)) if(BOOST_TEST(! ec))
{ BOOST_TEST(serialize(p.release()) == out);
BOOST_TEST(serialize(p.release(ec)) == out);
BOOST_TEST(! ec);
}
} }
void void

View File

@ -759,9 +759,11 @@ usingParsing()
if( ! ec ) if( ! ec )
p.finish( ec ); p.finish( ec );
if( ec )
return;
// Take ownership of the resulting value. // Take ownership of the resulting value.
value jv = p.release( ec ); value jv = p.release();
// At this point the parser may be re-used by calling p.reset() again. // At this point the parser may be re-used by calling p.reset() again.
@ -785,12 +787,11 @@ usingParsing()
p.write( "3,4,5]", 6, ec ); p.write( "3,4,5]", 6, ec );
if(! ec) if(! ec)
p.finish( ec ); p.finish( ec );
if( ec )
return;
// Take ownership of the resulting value. // Take ownership of the resulting value.
if(! ec) value jv = p.release( );
value jv = p.release( ec );
assert(! ec );
// At this point the parser may be re-used by calling p.reset() again. // At this point the parser may be re-used by calling p.reset() again.
@ -812,9 +813,11 @@ usingParsing()
p.write( "[1,2,3,4,5]", 11, ec ); p.write( "[1,2,3,4,5]", 11, ec );
if( ! ec ) if( ! ec )
p.finish( ec ); p.finish( ec );
if( ec )
return;
// The value will use the monotonic resource created above // The value will use the monotonic resource created above
value jv = p.release( ec ); value jv = p.release();
} }
//] //]
@ -836,9 +839,7 @@ usingParsing()
assert( ! ec ); assert( ! ec );
value jv = p.release( ec ); value jv = p.release();
assert( ! ec );
// The intermediate storage that was used // The intermediate storage that was used
// for the last value will be reused here. // for the last value will be reused here.
@ -850,9 +851,7 @@ usingParsing()
assert( ! ec ); assert( ! ec );
jv = p.release( ec ); jv = p.release();
assert( ! ec );
//] //]
} }