Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes for addressbook-query filters #1322

Merged

Conversation

mstilkerich
Copy link
Contributor

A null dereference occurs when a param-filter is checked on a property that does not have this parameter set. I adapted the tests by simply rearranging the test data set so that a TEL property without TYPE parameter comes before those with TYPE parameters to trigger the situation in the existing tests.

A log trace for your reference:

>>>>>>>>
REPORT /dav.php/addressbooks/mikey/default/ HTTP/1.1
Content-Length: 564
User-Agent: GuzzleHttp/7
Host: baikal.mike2k.de
Depth: 1
Content-Type: application/xml; charset=UTF-8

<?xml version="1.0"?>
<CARDDAV:addressbook-query xmlns:DAV="DAV:" xmlns:CARDDAV="urn:ietf:params:xml:ns:carddav" xmlns:CS="http://calendarserver.org/ns/">
 <DAV:prop>
  <DAV:getetag/>
  <CARDDAV:address-data/>
 </DAV:prop>
 <CARDDAV:filter test="anyof">
  <CARDDAV:prop-filter name="EMAIL" test="anyof">
   <CARDDAV:param-filter name="TYPE">
    <CARDDAV:text-match negate-condition="no" collation="i;unicode-casemap" match-type="equals">HOME</CARDDAV:text-match>
   </CARDDAV:param-filter>
  </CARDDAV:prop-filter>
 </CARDDAV:filter>
</CARDDAV:addressbook-query>

<<<<<<<<
HTTP/1.1 500 Internal Server Error
Date: Fri, 22 Jan 2021 16:12:53 GMT
Server: Apache/2.4.41 (Ubuntu)
WWW-Authenticate: Negotiate oYG3MIG0oAMKAQChCwYJKoZIhvcSAQICooGfBIGcYIGZBgkqhkiG9xIBAgICAG+BiTCBhqADAgEFoQMCAQ+iejB4oAMCARKicQRvPTYAJnGyjtnnnZ0mKrUTGmfrv16FDm6AOfELSH+Tr3gTActMMYpP0JsATIG+z3hNZ0cohyF9ovHkI4SnHfCu6XraiwezWRXUGN9pof70KKtCYZIjS2Ox+kVmh2ymZVuhzPteimH62rl5yViBSORq
Set-Cookie: PHPSESSID=5s804cp5rhd6r2i9iiv7aarfeq; path=/; HttpOnly
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
X-Sabre-Version: 4.1.2
Content-Length: 262
Connection: close
Content-Type: application/xml; charset=utf-8

<?xml version="1.0" encoding="utf-8"?>
<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">
  <s:sabredav-version>4.1.2</s:sabredav-version>
  <s:exception>Error</s:exception>
  <s:message>Call to a member function getValue() on null</s:message>
</d:error>

@codecov
Copy link

codecov bot commented Jan 23, 2021

Codecov Report

Merging #1322 (b5792d3) into master (82ea0e9) will increase coverage by 0.00%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master    #1322   +/-   ##
=========================================
  Coverage     97.12%   97.13%           
- Complexity     2788     2789    +1     
=========================================
  Files           174      174           
  Lines          8045     8050    +5     
=========================================
+ Hits           7814     7819    +5     
  Misses          231      231           
Impacted Files Coverage Δ Complexity Δ
lib/CardDAV/Plugin.php 96.92% <100.00%> (+0.04%) 122.00 <0.00> (+1.00)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 82ea0e9...b5792d3. Read the comment docs.

@mstilkerich
Copy link
Contributor Author

There is another issue in the same function. A negated text-match should match when a parameter value is found that does not match the search string. However, the current code requires there is no such parameter value. This is a problem if there are multiple instances of the property, where at least one matches the non-negated text-match filter, but there is also another one that matches the negated text-match filter. In this case, the function would filter out the card, because it searches for a property that matches the non-negated filter, and then stops and inverts the end result.

Example:

BEGIN:VCARD
VERSION:3.0
UID:3151DE6A-BC35-4612-B340-B53A034A2B27
FN:First Last
N:Last;First;;;
EMAIL;TYPE=HOME:home@example.com
EMAIL;TYPE=WORK:work@example.com
END:VCARD

A <prop-filter name="EMAIL"><param-filter name="TYPE"><text-match negate-condition="yes">HOME</text-match></param-filter></prop-filter> should match the card, because there is an EMAIL property that has no TYPE attribute that matches (the WORK address). But the current code returns false, because it finds a property that does match the non-negated filter (the HOME address), and then stops and inverts the result.

Relevant parts of RFC 6352:

Description:  The CARDDAV:prop-filter XML element specifies search criteria on a specific vCard property
       (e.g., "NICKNAME").  An address object is said to match a CARDDAV:prop-filter if:
      *  A vCard property of the type specified by the "name" attribute exists, and the CARDDAV:prop-filter is
         empty, or it matches any specified CARDDAV:text-match or CARDDAV:param-filter conditions.  The
        "test" attribute specifies whether any (logical OR) or all (logical AND) of the text-filter and
         param-filter tests need to match in order for the overall filter to match.
or:
      *  [...]
Description:  The CARDDAV:param-filter XML element specifies search criteria on a specific vCard
       property parameter (e.g., TYPE) in the scope of a given CARDDAV:prop-filter.  A vCard property
       is said to match a CARDDAV:param-filter if:
      *  A parameter of the type specified by the "name" attribute exists, and the
         CARDDAV:param-filter is empty, or it matches the CARDDAV:text-match conditions if specified.
or:
      *  [...]

@mstilkerich
Copy link
Contributor Author

mstilkerich commented Jan 23, 2021

There appears to be the same problem with negated text-matches at the prop-filter level. Fixed that as well.

@mstilkerich mstilkerich changed the title Fix null dereference on param-filter check Fixes for addressbook-query filters Jan 23, 2021
The negation applies to the individual text-match (i.e. the negated
text-match matches if a parameter string does not match the search
string). It does not apply to the entire param-filter (i.e. it does not
mean there must be NO property instance that matches the param filter,
it is sufficient if there is one that does not match).
The negate-condition attribute applies to the individual text-match, not
the result of applying the non-negated match against all property
instances of the asked for type.
@phil-davis phil-davis force-pushed the fix_addressbook_query_paramfilter branch from 568c60d to b5792d3 Compare February 12, 2021 05:47
Copy link
Contributor

@phil-davis phil-davis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - tests fail before the changes, and pass with the code changes, good stuff.

@phil-davis
Copy link
Contributor

I rebased. Let's see how many hours delay Travis has today!

@phil-davis phil-davis merged commit 012d643 into sabre-io:master Feb 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants