diff --git a/ext/nokogiri/html_sax_push_parser.c b/ext/nokogiri/html_sax_push_parser.c
index 3a739ae1d2f..af1dfd2b4fd 100644
--- a/ext/nokogiri/html_sax_push_parser.c
+++ b/ext/nokogiri/html_sax_push_parser.c
@@ -9,9 +9,10 @@
static VALUE native_write(VALUE self, VALUE _chunk, VALUE _last_chunk)
{
xmlParserCtxtPtr ctx;
- const char * chunk = NULL;
- int size = 0;
-
+ const char * chunk = NULL;
+ int size = 0;
+ int status = 0;
+ libxmlStructuredErrorHandlerState handler_state;
Data_Get_Struct(self, xmlParserCtxt, ctx);
@@ -20,13 +21,16 @@ static VALUE native_write(VALUE self, VALUE _chunk, VALUE _last_chunk)
size = (int)RSTRING_LEN(_chunk);
}
- xmlSetStructuredErrorFunc(NULL, NULL);
+ Nokogiri_structured_error_func_save_and_set(&handler_state, NULL, NULL);
+
+ status = htmlParseChunk(ctx, chunk, size, Qtrue == _last_chunk ? 1 : 0);
+
+ Nokogiri_structured_error_func_restore(&handler_state);
- if(htmlParseChunk(ctx, chunk, size, Qtrue == _last_chunk ? 1 : 0)) {
- if (!(ctx->options & XML_PARSE_RECOVER)) {
- xmlErrorPtr e = xmlCtxtGetLastError(ctx);
- Nokogiri_error_raise(NULL, e);
- }
+ if ((status != 0) && !(ctx->options & XML_PARSE_RECOVER)) {
+ // TODO: there appear to be no tests for this block
+ xmlErrorPtr e = xmlCtxtGetLastError(ctx);
+ Nokogiri_error_raise(NULL, e);
}
return self;
diff --git a/ext/nokogiri/xml_syntax_error.c b/ext/nokogiri/xml_syntax_error.c
index 0b240f05a5e..13da073da9e 100644
--- a/ext/nokogiri/xml_syntax_error.c
+++ b/ext/nokogiri/xml_syntax_error.c
@@ -1,5 +1,28 @@
#include
+void
+Nokogiri_structured_error_func_save(libxmlStructuredErrorHandlerState *handler_state)
+{
+ /* this method is tightly coupled to the implementation of xmlSetStructuredErrorFunc */
+ handler_state->user_data = xmlStructuredErrorContext;
+ handler_state->handler = xmlStructuredError;
+}
+
+void
+Nokogiri_structured_error_func_save_and_set(libxmlStructuredErrorHandlerState *handler_state,
+ void *user_data,
+ xmlStructuredErrorFunc handler)
+{
+ Nokogiri_structured_error_func_save(handler_state);
+ xmlSetStructuredErrorFunc(user_data, handler);
+}
+
+void
+Nokogiri_structured_error_func_restore(libxmlStructuredErrorHandlerState *handler_state)
+{
+ xmlSetStructuredErrorFunc(handler_state->user_data, handler_state->handler);
+}
+
void Nokogiri_error_array_pusher(void * ctx, xmlErrorPtr error)
{
VALUE list = (VALUE)ctx;
diff --git a/ext/nokogiri/xml_syntax_error.h b/ext/nokogiri/xml_syntax_error.h
index 58475cb8529..6994cb1ff59 100644
--- a/ext/nokogiri/xml_syntax_error.h
+++ b/ext/nokogiri/xml_syntax_error.h
@@ -3,11 +3,23 @@
#include
+typedef struct _libxmlStructuredErrorHandlerState {
+ void *user_data;
+ xmlStructuredErrorFunc handler;
+} libxmlStructuredErrorHandlerState ;
+
void init_xml_syntax_error();
+
+void Nokogiri_structured_error_func_save(libxmlStructuredErrorHandlerState *handler_state);
+void Nokogiri_structured_error_func_save_and_set(libxmlStructuredErrorHandlerState *handler_state,
+ void *user_data,
+ xmlStructuredErrorFunc handler);
+void Nokogiri_structured_error_func_restore(libxmlStructuredErrorHandlerState *handler_state);
+
VALUE Nokogiri_wrap_xml_syntax_error(xmlErrorPtr error);
-void Nokogiri_error_array_pusher(void * ctx, xmlErrorPtr error);
-NORETURN(void Nokogiri_error_raise(void * ctx, xmlErrorPtr error));
+void Nokogiri_error_array_pusher(void *ctx, xmlErrorPtr error);
+NORETURN(void Nokogiri_error_raise(void *ctx, xmlErrorPtr error));
extern VALUE cNokogiriXmlSyntaxError;
-#endif
+#endif /* NOKOGIRI_XML_SYNTAX_ERROR */