Deprecated: Function get_magic_quotes_gpc() is deprecated in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 99
Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 619
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 832
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
diff --git a/c_src/exml.cpp b/c_src/exml.cpp
index ab64b18..4a13092 100644
--- a/c_src/exml.cpp
+++ b/c_src/exml.cpp
@@ -81,7 +81,7 @@ namespace {
struct Parser {
ustring stream_tag;
- std::uint64_t max_child_size = 0;
+ std::uint64_t max_element_size = 0;
bool infinite_stream = false;
static thread_local std::vector buffer;
@@ -459,10 +459,10 @@ static ERL_NIF_TERM create(ErlNifEnv *env, int argc,
void *mem = enif_alloc_resource(parser_type, sizeof(Parser));
Parser *parser = new (mem) Parser;
- ErlNifUInt64 max_child_size;
- if (!enif_get_uint64(env, argv[0], &max_child_size))
+ ErlNifUInt64 max_element_size;
+ if (!enif_get_uint64(env, argv[0], &max_element_size))
return enif_make_badarg(env);
- parser->max_child_size = static_cast(max_child_size);
+ parser->max_element_size = static_cast(max_element_size);
if (enif_compare(atom_true, argv[1]) == 0)
parser->infinite_stream = true;
@@ -491,6 +491,7 @@ static ERL_NIF_TERM parse_next(ErlNifEnv *env, int argc,
ParseCtx ctx{env, parser};
xml_document::ParseResult result;
ERL_NIF_TERM element;
+ const char *error_msg = nullptr;
xml_document &doc = get_static_doc();
Parser::term_buffer.clear();
@@ -498,10 +499,15 @@ static ERL_NIF_TERM parse_next(ErlNifEnv *env, int argc,
auto parseStreamOpen = [&] {
result = doc.parse(Parser::buffer.data() + offset);
if (!result.has_error) {
- auto name_tag = node_name(doc.impl.first_node());
- parser->stream_tag =
+ if (parser->max_element_size &&
+ result.rest - Parser::buffer.data() - offset > parser->max_element_size) {
+ error_msg = "element too big";
+ } else {
+ auto name_tag = node_name(doc.impl.first_node());
+ parser->stream_tag =
ustring{std::get<0>(name_tag), std::get<1>(name_tag)};
- element = make_stream_start_tuple(ctx, doc.impl.first_node());
+ element = make_stream_start_tuple(ctx, doc.impl.first_node());
+ }
}
};
@@ -515,10 +521,20 @@ static ERL_NIF_TERM parse_next(ErlNifEnv *env, int argc,
parser->stream_tag;
};
- if (parser->infinite_stream) {
+ auto parseElement = [&] {
result = doc.parse(Parser::buffer.data() + offset);
- if (!result.has_error)
- element = make_xmlel(ctx, doc.impl.first_node());
+ if (!result.has_error) {
+ if (parser->max_element_size &&
+ result.rest - Parser::buffer.data() - offset > parser->max_element_size) {
+ error_msg = "element too big";
+ } else {
+ element = make_xmlel(ctx, doc.impl.first_node());
+ }
+ }
+ };
+
+ if (parser->infinite_stream) {
+ parseElement();
} else if (parser->stream_tag.empty()) {
parseStreamOpen();
} else if (has_stream_closing_tag(parser, offset)) {
@@ -527,9 +543,7 @@ static ERL_NIF_TERM parse_next(ErlNifEnv *env, int argc,
result.rest = &*Parser::buffer.rbegin();
element = make_stream_end_tuple(ctx);
} else {
- result = doc.parse(Parser::buffer.data() + offset);
- if (!result.has_error)
- element = make_xmlel(ctx, doc.impl.first_node());
+ parseElement();
}
if (result.eof && hasStreamReopen()) {
@@ -538,26 +552,30 @@ static ERL_NIF_TERM parse_next(ErlNifEnv *env, int argc,
}
if (result.eof) {
- if (parser->max_child_size &&
- Parser::buffer.size() - offset >= parser->max_child_size)
- return enif_make_tuple2(
- env, atom_error,
- enif_make_string(env, "child element too big", ERL_NIF_LATIN1));
-
- result.rest = Parser::buffer.data() + offset;
- element = atom_undefined;
+ // Return an error if an incomplete element has at least max_element_size characters.
+ if (parser->max_element_size &&
+ Parser::buffer.size() - offset > parser->max_element_size) {
+ error_msg = "element too big";
+ } else {
+ result.rest = Parser::buffer.data() + offset;
+ element = atom_undefined;
+ }
} else if (result.has_error) {
- return enif_make_tuple2(
- env, atom_error,
- enif_make_string(env, result.error_message.c_str(), ERL_NIF_LATIN1));
+ error_msg = result.error_message.c_str();
+ }
+
+ if (!error_msg) {
+ // Return an error when null character is found.
+ std::size_t rest_size = &Parser::buffer.back() - result.rest;
+ if (std::strlen(reinterpret_cast(result.rest)) != rest_size)
+ error_msg = "null character found in buffer";
}
- // Raise an exception when null character is found.
- std::size_t rest_size = &Parser::buffer.back() - result.rest;
- if (std::strlen(reinterpret_cast(result.rest)) != rest_size)
+ if (error_msg) {
return enif_make_tuple2(
env, atom_error,
- enif_make_string(env, "null character found in buffer", ERL_NIF_LATIN1));
+ enif_make_string(env, error_msg, ERL_NIF_LATIN1));
+ }
return enif_make_tuple3(
env, atom_ok, element,
diff --git a/rebar.config b/rebar.config
index 038fa48..30fa210 100644
--- a/rebar.config
+++ b/rebar.config
@@ -25,6 +25,7 @@
]}
]}.
+{project_plugins, [rebar3_ex_doc]}.
{plugins, [pc, rebar3_hex]}.
% Interrupt compilation, if the artifact is not found
diff --git a/src/exml_stream.erl b/src/exml_stream.erl
index 9a58986..9a276f3 100644
--- a/src/exml_stream.erl
+++ b/src/exml_stream.erl
@@ -29,11 +29,11 @@
-type stop() :: #xmlstreamend{}.
-type element() :: exml_nif:stream_element().
-type parser() :: #parser{}.
-%% infinite_stream - no distinct "stream start" or "stream end", only #xmlel{} will be returned
-%% max_child_size - specifies maximum byte size of any child of the root element. The byte size is
-%% counted from the start tag until the opening character of its end tag. Disabled
-%% if set to 0 (default).
--type parser_opt() :: {infinite_stream, boolean()} | {max_child_size, non_neg_integer()}.
+%% infinite_stream - No distinct "stream start" or "stream end", only #xmlel{} will be returned.
+%% max_element_size - Specifies maximum byte size of any parsed XML element.
+%% The only exception is the "stream start" element,
+%% for which only the size of the opening tag is limited.
+-type parser_opt() :: {infinite_stream, boolean()} | {max_element_size, non_neg_integer()}.
%%%===================================================================
%%% Public API
@@ -45,9 +45,9 @@ new_parser() ->
-spec new_parser([parser_opt()]) -> {ok, parser()} | {error, any()}.
new_parser(Opts)->
- MaxChildSize = proplists:get_value(max_child_size, Opts, 0),
+ MaxElementSize = proplists:get_value(max_element_size, Opts, 0),
InfiniteStream = proplists:get_value(infinite_stream, Opts, false),
- case exml_nif:create(MaxChildSize, InfiniteStream) of
+ case exml_nif:create(MaxElementSize, InfiniteStream) of
{ok, EventParser} ->
{ok, #parser{event_parser = EventParser, buffer = []}};
Error ->
diff --git a/test/exml_stream_tests.erl b/test/exml_stream_tests.erl
index 99b8e0a..e5e43c7 100644
--- a/test/exml_stream_tests.erl
+++ b/test/exml_stream_tests.erl
@@ -160,7 +160,7 @@ conv_attr_test() ->
-define(RESTART_TEST_STREAM, <<"
">>).
stream_restarts_test() ->
- {ok, Parser0} = exml_stream:new_parser([{start_tag, <<"stream:stream">>}]),
+ {ok, Parser0} = exml_stream:new_parser([]),
{ok, _Parser1, Elements} = exml_stream:parse(Parser0, ?RESTART_TEST_STREAM),
?assertMatch(
[#xmlstreamstart{name = <<"stream:stream">>},
@@ -174,7 +174,7 @@ stream_restarts_test() ->
"">>).
stream_restarts_with_xml_declaration_test() ->
- {ok, Parser0} = exml_stream:new_parser([{start_tag, <<"stream:stream">>}]),
+ {ok, Parser0} = exml_stream:new_parser([]),
{ok, _Parser1, Elements} = exml_stream:parse(Parser0, ?RESTART_TEST_STREAM_XMLDEC),
?assertMatch(
[#xmlstreamstart{name = <<"stream:stream">>},
@@ -183,14 +183,53 @@ stream_restarts_with_xml_declaration_test() ->
#xmlel{name = <<"other">>}],
Elements).
-stream_max_child_size_test() ->
- {ok, Parser0} = exml_stream:new_parser([{max_child_size, 15}]),
- {ok, Parser1, _} = exml_stream:parse(Parser0, <<"">>),
- {ok, Parser2, _} = exml_stream:parse(Parser1, <<"">>),
- ?assertEqual({error, "child element too big"}, exml_stream:parse(Parser2, <<"456">>)).
+stream_max_opening_tag_size_test() ->
+ {ok, Parser0} = exml_stream:new_parser([{max_element_size, 10}]),
+ ?assertMatch({ok, _Parser1, [#xmlstreamstart{},
+ #xmlel{}]}, exml_stream:parse(Parser0, <<"">>)),
+ {ok, Parser2} = exml_stream:new_parser([{max_element_size, 9}]),
+ ?assertEqual({error, "element too big"}, exml_stream:parse(Parser2, <<"">>)).
+
+stream_max_element_size_test() ->
+ {ok, Parser0} = exml_stream:new_parser([{max_element_size, 10}]),
+ {ok, Parser1, Elements0} = exml_stream:parse(Parser0, <<"">>),
+ ?assertMatch([#xmlstreamstart{}, #xmlel{}], Elements0),
+ ?assertEqual({error, "element too big"}, exml_stream:parse(Parser1, <<"">>)).
+
+stream_max_text_element_size_test() ->
+ {ok, Parser0} = exml_stream:new_parser([{max_element_size, 10}]),
+ {ok, Parser1, Elements0} = exml_stream:parse(Parser0, <<"123123">>),
+ ?assertMatch([#xmlstreamstart{}, #xmlel{}, #xmlel{}], Elements0),
+ ?assertEqual({error, "element too big"}, exml_stream:parse(Parser1, <<"1234">>)).
+
+stream_max_incomplete_element_size_test() ->
+ {ok, Parser0} = exml_stream:new_parser([{max_element_size, 10}]),
+ {ok, Parser1, Elements0} = exml_stream:parse(Parser0, <<"123123">>),
+ ?assertMatch([#xmlstreamstart{}, #xmlel{}, #xmlel{}], Elements0),
+ %% Element has 10 characters, but it's incomplete, so it would be too big
+ ?assertEqual({error, "element too big"}, exml_stream:parse(Parser1, <<"1234>)).
+
+stream_max_chunked_element_size_test() ->
+ {ok, Parser0} = exml_stream:new_parser([{max_element_size, 10}]),
+ {ok, Parser1, Elements0} = exml_stream:parse(Parser0, <<"">>),
+ ?assertMatch([#xmlstreamstart{}], Elements0),
+ ?assertEqual({error, "element too big"}, exml_stream:parse(Parser1, <<" ">>)).
+
+stream_max_root_element_size_test() ->
+ {ok, Parser0} = exml_stream:new_parser([{max_element_size, 10}, {infinite_stream, true}]),
+ {ok, Parser1, Elements0} = exml_stream:parse(Parser0, <<"123123">>),
+ ?assertMatch([#xmlel{}, #xmlel{}], Elements0),
+ ?assertEqual({error, "element too big"}, exml_stream:parse(Parser1, <<"">>)).
+
+stream_max_incomplete_root_element_size_test() ->
+ {ok, Parser0} = exml_stream:new_parser([{max_element_size, 10}, {infinite_stream, true}]),
+ {ok, Parser1, Elements0} = exml_stream:parse(Parser0, <<"123123">>),
+ ?assertMatch([#xmlel{}, #xmlel{}], Elements0),
+ %% Element has 10 characters, but it will have at least one more character
+ ?assertEqual({error, "element too big"}, exml_stream:parse(Parser1, <<"1234>)).
infinite_stream_partial_chunk_test() ->
- {ok, Parser0} = exml_stream:new_parser([{infinite_stream, true}, {autoreset, true}]),
+ {ok, Parser0} = exml_stream:new_parser([{infinite_stream, true}]),
{ok, Parser1, Open} = exml_stream:parse(Parser0, <<"">>),
?assertEqual(
[#xmlel{name = <<"open">>,