Skip to content

Commit f9a2c4e

Browse files
committed
fix: restore proper error handling in the SAX push parser
originally introduced in 771164d but broken in the recent commits. This is an incomplete fix. We should adopt this same strategy of save-and-restore everywhere we set the error handlers.
1 parent 35aa88b commit f9a2c4e

File tree

3 files changed

+51
-12
lines changed

3 files changed

+51
-12
lines changed

ext/nokogiri/html_sax_push_parser.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@
99
static VALUE native_write(VALUE self, VALUE _chunk, VALUE _last_chunk)
1010
{
1111
xmlParserCtxtPtr ctx;
12-
const char * chunk = NULL;
13-
int size = 0;
14-
12+
const char * chunk = NULL;
13+
int size = 0;
14+
int status = 0;
15+
libxmlStructuredErrorHandlerState handler_state;
1516

1617
Data_Get_Struct(self, xmlParserCtxt, ctx);
1718

@@ -20,13 +21,16 @@ static VALUE native_write(VALUE self, VALUE _chunk, VALUE _last_chunk)
2021
size = (int)RSTRING_LEN(_chunk);
2122
}
2223

23-
xmlSetStructuredErrorFunc(NULL, NULL);
24+
Nokogiri_structured_error_func_save_and_set(&handler_state, NULL, NULL);
25+
26+
status = htmlParseChunk(ctx, chunk, size, Qtrue == _last_chunk ? 1 : 0);
27+
28+
Nokogiri_structured_error_func_restore(&handler_state);
2429

25-
if(htmlParseChunk(ctx, chunk, size, Qtrue == _last_chunk ? 1 : 0)) {
26-
if (!(ctx->options & XML_PARSE_RECOVER)) {
27-
xmlErrorPtr e = xmlCtxtGetLastError(ctx);
28-
Nokogiri_error_raise(NULL, e);
29-
}
30+
if ((status != 0) && !(ctx->options & XML_PARSE_RECOVER)) {
31+
// TODO: there appear to be no tests for this block
32+
xmlErrorPtr e = xmlCtxtGetLastError(ctx);
33+
Nokogiri_error_raise(NULL, e);
3034
}
3135

3236
return self;

ext/nokogiri/xml_syntax_error.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,28 @@
11
#include <xml_syntax_error.h>
22

3+
void
4+
Nokogiri_structured_error_func_save(libxmlStructuredErrorHandlerState *handler_state)
5+
{
6+
/* this method is tightly coupled to the implementation of xmlSetStructuredErrorFunc */
7+
handler_state->user_data = xmlStructuredErrorContext;
8+
handler_state->handler = xmlStructuredError;
9+
}
10+
11+
void
12+
Nokogiri_structured_error_func_save_and_set(libxmlStructuredErrorHandlerState *handler_state,
13+
void *user_data,
14+
xmlStructuredErrorFunc handler)
15+
{
16+
Nokogiri_structured_error_func_save(handler_state);
17+
xmlSetStructuredErrorFunc(user_data, handler);
18+
}
19+
20+
void
21+
Nokogiri_structured_error_func_restore(libxmlStructuredErrorHandlerState *handler_state)
22+
{
23+
xmlSetStructuredErrorFunc(handler_state->user_data, handler_state->handler);
24+
}
25+
326
void Nokogiri_error_array_pusher(void * ctx, xmlErrorPtr error)
427
{
528
VALUE list = (VALUE)ctx;

ext/nokogiri/xml_syntax_error.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,23 @@
33

44
#include <nokogiri.h>
55

6+
typedef struct _libxmlStructuredErrorHandlerState {
7+
void *user_data;
8+
xmlStructuredErrorFunc handler;
9+
} libxmlStructuredErrorHandlerState ;
10+
611
void init_xml_syntax_error();
12+
13+
void Nokogiri_structured_error_func_save(libxmlStructuredErrorHandlerState *handler_state);
14+
void Nokogiri_structured_error_func_save_and_set(libxmlStructuredErrorHandlerState *handler_state,
15+
void *user_data,
16+
xmlStructuredErrorFunc handler);
17+
void Nokogiri_structured_error_func_restore(libxmlStructuredErrorHandlerState *handler_state);
18+
719
VALUE Nokogiri_wrap_xml_syntax_error(xmlErrorPtr error);
8-
void Nokogiri_error_array_pusher(void * ctx, xmlErrorPtr error);
9-
NORETURN(void Nokogiri_error_raise(void * ctx, xmlErrorPtr error));
20+
void Nokogiri_error_array_pusher(void *ctx, xmlErrorPtr error);
21+
NORETURN(void Nokogiri_error_raise(void *ctx, xmlErrorPtr error));
1022

1123
extern VALUE cNokogiriXmlSyntaxError;
12-
#endif
1324

25+
#endif /* NOKOGIRI_XML_SYNTAX_ERROR */

0 commit comments

Comments
 (0)