Richard Zowalla created OPENNLP-1946:
----------------------------------------

             Summary: UrlCharSequenceNormalizer misses or partially removes 
many URLs from the WPT URL test suite
                 Key: OPENNLP-1946
                 URL: https://issues.apache.org/jira/browse/OPENNLP-1946
             Project: OpenNLP
          Issue Type: Improvement
            Reporter: Richard Zowalla


h3. Background

UrlCharSequenceNormalizer replaces URLs and email addresses with a space. Its 
URL rule is {{https?://}} followed by {{\[\-_.?&\~;\+=/#0\-9A\-Za\-z\]\+}}. Its 
email rule is 
{{\(?<\!\[\-\+_.0\-9A\-Za\-z\]\)\[\-\+\_.0\-9A\-Za\-z\]\+@\[\-0\-9A\-Za\-z\]\+\[\-.0\-9A\-Za\-z\]\+}}.
 It is part of the default normalizer chain in LanguageDetectorFactory.

We ran all 893 cases from the WHATWG URL test suite 
\(web\-platform\-tests/wpt@3e62dcd8d2968379e0a77fd7b7763de2304883cc, 
url/resources/urltestdata.json\) through the normalizer. The regex version 
\(2.5.12\) and the cursor\-scan version \(main, OPENNLP\-1876\) produce 
identical output for every input, so the gaps below are in the original design, 
not in the port.

h3. Results

||Bucket||WPT verdict||Expected||Pass||Fail||
|A1|valid http\(s\), written as scheme://|whole URL removed|54|114|
|A2|valid http\(s\), unusual form \(http:foo, http:\, http:/x\)|whole URL 
removed|0|24|
|B|invalid URL|input unchanged|123|39 fully \+ 107 partly removed|
|C|valid URL with another scheme|not partly removed|269|9|
|D|relative reference|input unchanged|154|0|

h3. Findings

_1. Valid http\(s\) URLs are cut short \(114\)._ The match ends at the first 
character outside the body set:
\* {{:}} for a port or user:pass \(27\): {{[http://f:21/}|http://f:21/}]} \-> 
{{" :21/"}}
\* {{%}} escapes \(25\): 
{{[http://example.com/%20foo}|http://example.com/%20foo}]} \-> {{" %20foo"}}
\* non\-ASCII / IDN hostnames and paths \(21\)
\* ASCII punctuation such as {{" \ < > ` ' \( { \!}} \(15\)
\* tabs, newlines and control characters \(13\)
\* {{\[}} in IPv6 hosts \(7\): {{http://\[::1\]/}} is not matched at all
\* {{@}} in userinfo \(6\)

_2. Matches start inside other schemes \(no left boundary\)._
\* {{git\+[https://github.com/foo/bar}|https://github.com/foo/bar}]} \-> 
{{"git\+ "}}
\* {{blob:[https://example.com:443/}|https://example.com:443/}]} \-> {{"blob: 
:443/"}}

_3. The email pass removes the password and host from userinfo._
\* {{telnet://user:[email protected]:23/}} \-> {{"telnet://user: :23/"}}
\* the same happens for redis://, rsync:// and tag:

_4. Invalid hosts are removed as URLs \(39\)._ Examples: 
{{[http://256.256.256.256}|http://256.256.256.256}]}, 
{{[http://1.2.3.08}|http://1.2.3.08}]}, {{[http://foo.0x4}|http://foo.0x4}]}, 
{{http://?}}, {{http://#}}. This is low priority, because a text normalizer 
does not need to validate hosts.

h3. Proposal

Changing the default output would change the features that existing language 
detector models were trained on. Therefore:

h1. Keep {{UrlCharSequenceNormalizer.getInstance\(\)}} and the 
LanguageDetectorFactory chain byte\-for\-byte unchanged. Document the known 
limits \(findings 1\-3\) in the class Javadoc.
h1. Add an opt\-in variant \(for example a separate instance or a builder 
flag\) that:
#\* requires a non\-word character or start of text before the scheme \(finding 
2\)
#\* matches the scheme case\-insensitively
#\* accepts a port, userinfo, percent escapes, bracketed IPv6 hosts, and 
non\-ASCII hostnames and paths in the body \(finding 1\)
#\* stops at whitespace, control characters, and {{< > "}} as delimiters, which 
is how URLs are bounded in running text
#\* runs the URL pass before the email pass without email\-matching inside URL 
userinfo \(finding 3\)

h1. Add a test that runs the WPT data \(pinned commit; the data is 3\-clause 
BSD, so vendoring it needs a LICENSE/NOTICE entry, or a curated subset is kept 
instead\) against both variants: the default pins current output, the opt\-in 
variant asserts buckets A1 and C.
Out of scope: validating hosts \(finding 4\), the unusual forms in bucket A2, 
and schemes other than http\(s\).





--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to