mirror of
https://github.com/dgtlmoon/changedetection.io.git
synced 2026-10-25 16:18:32 +00:00
Fix IndexError on empty/whitespace-only JSON content (#4534)
extract_json_blob_from_html() and extract_json_as_string() both peeked at content_start[0] to decide whether the body looks like JSON. A blank body leaves content_start empty, so the peek raised IndexError instead of the watch reporting that no JSON was found. Guard the index in both places so empty and whitespace-only content takes the same JSONNotFound path as any other non-JSON body. Fixes #4531 Co-authored-by: Yi-111-a <yi-111-a@users.noreply.github.com>
This commit is contained in:
1 parent
e3e51a3a33
commit
b82750421b
2 files changed
+27
-2
No files matched your search
@@ -630,7 +630,7 @@ def extract_json_blob_from_html(content, ensure_is_ldjson_info_type, json_filter
|
||||
# result.text is how bs4 magically strips JSON from the body
|
||||
content_start = result.text.lstrip("\ufeff").strip()[:100] if result.text else ''
|
||||
# Skip empty tags, and things that dont even look like JSON
|
||||
if not result.text or not (content_start[0] == '{' or content_start[0] == '['):
|
||||
if not content_start or not (content_start[0] == '{' or content_start[0] == '['):
|
||||
continue
|
||||
try:
|
||||
json_data = json.loads(result.text)
|
||||
@@ -682,7 +682,7 @@ def extract_json_as_string(content, json_filter, ensure_is_ldjson_info_type=None
|
||||
|
||||
content_start = content.lstrip("\ufeff").strip()[:100]
|
||||
|
||||
if content_start[0] == '{' or content_start[0] == '[':
|
||||
if content_start and (content_start[0] == '{' or content_start[0] == '['):
|
||||
try:
|
||||
# .lstrip("\ufeff") strings ByteOrderMark from UTF8 and still lets the UTF work
|
||||
stripped_text_from_html = _parse_json(json.loads(content.lstrip("\ufeff")), json_filter)
|
||||
|
||||
@@ -121,6 +121,31 @@ and it can also be repeated
|
||||
html_tools.extract_json_as_string('COMPLETE GIBBERISH, NO JSON!', "jqraw:.id")
|
||||
|
||||
|
||||
def test_blank_content_does_not_raise_indexerror():
|
||||
"""Empty / whitespace-only content must take the normal JSONNotFound path, not crash.
|
||||
|
||||
The content-sniffing peeked at content_start[0] to see if the body looked like JSON.
|
||||
A blank body left content_start empty, so that peek raised IndexError instead of
|
||||
letting the caller report 'no JSON found' the way any other non-JSON body does.
|
||||
See https://github.com/dgtlmoon/changedetection.io/issues/4531
|
||||
"""
|
||||
from .. import html_tools
|
||||
|
||||
# Blank bodies with a json: filter set - the same as any other non-JSON content
|
||||
for blank in ('', ' ', '\n', '\r\n\t '):
|
||||
with pytest.raises(html_tools.JSONNotFound):
|
||||
html_tools.extract_json_as_string(blank, "json:$.id")
|
||||
|
||||
# Same on the html blob path, where a whitespace-only <script> or <body> is skipped
|
||||
# and the real ld+json that follows it is still found
|
||||
html = '<html><script>\n</script><script type="application/ld+json">{"a":1}</script></html>'
|
||||
assert html_tools.extract_json_blob_from_html(html, None, "json:$.a") == "1"
|
||||
|
||||
# A document that is nothing but blank markup has no JSON in it at all
|
||||
with pytest.raises(html_tools.JSONNotFound):
|
||||
html_tools.extract_json_blob_from_html('<html><body> </body></html>', None, "json:$.a")
|
||||
|
||||
|
||||
def test_lone_surrogate_escapes_do_not_break_filters():
|
||||
"""A \\uD800-style escape in the watched JSON must not take the whole document down.
|
||||
|
||||
|
||||
Reference in new issue
Block a user