Skip to content

Fix XPath variable handling and invalid value contamination#342

Open
tompng wants to merge 1 commit into
ruby:masterfrom
tompng:fix_xpath_nil_contamination
Open

Fix XPath variable handling and invalid value contamination#342
tompng wants to merge 1 commit into
ruby:masterfrom
tompng:fix_xpath_nil_contamination

Conversation

@tompng

@tompng tompng commented Jun 28, 2026

Copy link
Copy Markdown
Member

Fix nil and other invalid value contamination. Nil can be injected through variables and through id function.
Unimplemented function id() is fixed to return [] instead of nil.
Add variable coerce and predicates after variables.

Minor behavior changes for an invalid XPath match:

doc = REXML::Document.new("<root/>")
REXML::XPath.match(doc, '($x)[1<2]', {}, {'x'=>42})
#=> [42] → []
REXML::XPath.match(doc, '$x[1<2]', {}, {'x'=>42})
#=> [42] → []

It may raise TypeError (because $x wasn't evaluated to a nodeset), though, it shoudn't return [42]

Note

Although nodeset as a variable has been accepted before, the code added in pull request explicitly permits it.
Nokogiri only accepts string value as a variable, so there's an option to limit the value types here.
Accepting nodeset may cause a problem if the passed nodes doesn't belong to a single document root. (or just consider such case as unsupported)

Copilot AI review requested due to automatic review settings June 28, 2026 08:40

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts REXML’s XPath evaluation to prevent nil/invalid values from “contaminating” results, primarily by making id() return an empty node-set and by coercing variable values + applying remaining predicates/steps after variable/group evaluation.

Changes:

  • Make unimplemented XPath function id() return [] (empty node-set) instead of nil.
  • Add variable coercion and ensure remaining predicates/steps are applied after variable and grouped expressions.
  • Add/extend tests covering id() and variable handling (including invalid predicate application on non-node-set variables).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
test/xpath/test_base.rb Adds regression tests for id() and variable coercion/predicate behavior.
lib/rexml/xpath_parser.rb Implements variable coercion and applies remaining predicates after variable/group evaluation.
lib/rexml/functions.rb Changes id() to return an empty node-set ([]).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/rexml/xpath_parser.rb
Comment on lines +348 to +357
def coerce_variable(value)
case value
when Array
value.grep(REXML::Node).uniq
when Numeric, String, true, false
value
else
""
end
end
Comment thread test/xpath/test_base.rb Outdated
assert_equal(["e"], XPath.match(doc, "//e[preceding-sibling::* = '1']").map(&:name))
end

def test_unimplemented_id_shouldnot_contaminate_nil
Fix nil and other invalid value contamination. Nil can be injected through variables and through id function.
Unimplemented function `id()` is fixed to return `[]` instead of `nil`.
Add variable coerce and predicates after variables.
@tompng tompng force-pushed the fix_xpath_nil_contamination branch from 3f20d0b to f343f5b Compare June 28, 2026 09:23
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.

2 participants