Skip to content

MLE-28100 MLE-29561: fix ResourceSequence leak in ContentOutputFormat initialize() and null pointer dereference in NodeImpl.isEqualNode()#605

Open
vshaniga wants to merge 1 commit into
developfrom
MLE-28100-MLE-29561-fix-mlcp-resource-leak-and-null-ptr
Open

MLE-28100 MLE-29561: fix ResourceSequence leak in ContentOutputFormat initialize() and null pointer dereference in NodeImpl.isEqualNode()#605
vshaniga wants to merge 1 commit into
developfrom
MLE-28100-MLE-29561-fix-mlcp-resource-leak-and-null-ptr

Conversation

@vshaniga
Copy link
Copy Markdown
Collaborator

MLE-28100 — Fix ResultSequence leak in ContentOutputFormat.initialize()

Problem:

  • initialize() called session.submitRequest(query) and stored the result in a ResultSequence, but never closed it. On repeated initializations or exception paths, this leaked server-side connections and sockets.

Fix:

  • Wrapped the submitRequest call and result-reading logic in a try/finally block that calls result.close().

File: src/main/java/com/marklogic/mapreduce/ContentOutputFormat.java


MLE-29561 — Fix NULL pointer dereference and logic bugs in NodeImpl.isEqualNode()

Problem:
Three logic bugs in isEqualNode():

  1. The hasChildNodes() guard was used to enter the attributes comparison block — getAttributes() could return null if the node has no attributes, causing a NPE.
  2. The hasAttributes() guard was used to enter the child nodes comparison block — incorrect semantics.
  3. Both isEqualNode() comparisons were missing negation — the method returned false when nodes were equal instead of when they were not equal.

Fix:

  • Swapped hasAttributes() / hasChildNodes() guards to match their respective blocks.
  • Added ! negation to both isEqualNode() comparisons.

File: src/main/java/com/marklogic/dom/NodeImpl.java


Tests

  • Ran unit tests → All passed
  • Ran 06mlcp test suite → No regression failures were found

….initialize() and null pointer dereference in NodeImpl.isEqualNode()
@vshaniga vshaniga self-assigned this May 22, 2026
Copilot AI review requested due to automatic review settings May 22, 2026 06:33
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes two correctness issues in mlcp’s Java code: (1) properly closing XCC ResultSequence created during ContentOutputFormat.initialize() to avoid leaking server-side resources, and (2) correcting guard logic and comparisons in NodeImpl.isEqualNode() to prevent NPEs and incorrect equality results.

Changes:

  • Wrap session.submitRequest(query) / result parsing in ContentOutputFormat.initialize() with try/finally to always close ResultSequence.
  • Fix NodeImpl.isEqualNode() to use the correct hasAttributes() / hasChildNodes() guards and negate mismatch comparisons.

Reviewed changes

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

File Description
src/main/java/com/marklogic/mapreduce/ContentOutputFormat.java Adds try/finally to close ResultSequence and refactors initialization result parsing.
src/main/java/com/marklogic/dom/NodeImpl.java Fixes equality logic to avoid NPE and correct boolean comparison semantics.

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

Comment on lines +433 to +441
} else {
// check if input needs to be in HTTP compliant mode
String inputRestrictHost = conf.getTrimmed(INPUT_RESTRICT_HOSTS);
if (inputRestrictHost == null ||
inputRestrictHost.equalsIgnoreCase("false")) {
HttpChannel.setUseHTTP(false);
if (LOG.isDebugEnabled()) {
LOG.debug("HTTP compliant mode disabled since x-forwarded-for doesn't exist");
}
Comment on lines +485 to 504
// initialize fastload mode
if (conf.get(OUTPUT_FAST_LOAD) == null) {
// fastload not set
if (conf.get(OUTPUT_DIRECTORY) != null) {
// output_dir is set, attempt to do fastload
if(conf.get(OUTPUT_PARTITION) == null &&
(policy == AssignmentPolicy.Kind.RANGE ||
policy == AssignmentPolicy.Kind.QUERY)) {
fastLoad = false;
} else if (policy == AssignmentPolicy.Kind.RANGE ||
policy == AssignmentPolicy.Kind.QUERY ||
policy == AssignmentPolicy.Kind.STATISTICAL) {
fastLoad = allowFastLoad;
} else {
fastLoad = true;
}
} else {
fastLoad = true;
//neither fastload nor output_dir is set
fastLoad = false;
}
Comment on lines 312 to 348
public boolean isEqualNode(Node other) {

// Note that normalization can affect equality; to avoid this,
// nodes should be normalized before being compared.
// For the moment, normalization cannot be done.
if (other==null) return false;
if (getNodeType() != other.getNodeType())
return false;
if (notequals(getLocalName(),other.getLocalName()))
return false;
if (notequals(getNamespaceURI(),other.getNamespaceURI()))
return false;
if (notequals(getPrefix(), other.getPrefix()))
return false;
if (notequals(getNodeValue(),other.getNodeValue()))
return false;
if (hasChildNodes() != other.hasChildNodes())
return false;
if (hasAttributes() != other.hasAttributes())
return false;
if (hasChildNodes()) {
if (hasAttributes()) {
NamedNodeMap thisAttr = getAttributes();
NamedNodeMap otherAttr = other.getAttributes();
if (thisAttr.getLength() != otherAttr.getLength())
return false;
for (int i = 0; i < thisAttr.getLength(); i++)
if (thisAttr.item(i).isEqualNode(otherAttr.item(i)))
if (!thisAttr.item(i).isEqualNode(otherAttr.item(i)))
return false;
}
if (hasAttributes()) {
if (hasChildNodes()) {
NodeList thisChild = getChildNodes();
NodeList otherChild = other.getChildNodes();
if (thisChild.getLength() != otherChild.getLength())
return false;
for (int i = 0; i < thisChild.getLength(); i++)
if (thisChild.item(i).isEqualNode(otherChild.item(i)))
if (!thisChild.item(i).isEqualNode(otherChild.item(i)))
return false;
@vshaniga
Copy link
Copy Markdown
Collaborator Author

I just added a try/finally around the result handling and indented the inner code accordingly.
Most of the changes in the diff are whitespace/indentation related.

whitespace-ignored diff: https://github.com/marklogic/marklogic-contentpump/pull/605/changes?w=1

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