From b2be8582e5be791d68449c6f84dd37f893319eb9 Mon Sep 17 00:00:00 2001 From: vshaniga Date: Tue, 19 May 2026 00:00:26 -0700 Subject: [PATCH] MLE-28100 MLE-29561: fix ResourceSequence leak in ContentOutputFormat.initialize() and null pointer dereference in NodeImpl.isEqualNode() --- src/main/java/com/marklogic/dom/NodeImpl.java | 10 +- .../mapreduce/ContentOutputFormat.java | 182 +++++++++--------- 2 files changed, 99 insertions(+), 93 deletions(-) diff --git a/src/main/java/com/marklogic/dom/NodeImpl.java b/src/main/java/com/marklogic/dom/NodeImpl.java index c9fbce50c..f5c7eaf5a 100644 --- a/src/main/java/com/marklogic/dom/NodeImpl.java +++ b/src/main/java/com/marklogic/dom/NodeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2024 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. + * Copyright (c) 2011-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -329,22 +329,22 @@ public boolean isEqualNode(Node other) { 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; } return true; diff --git a/src/main/java/com/marklogic/mapreduce/ContentOutputFormat.java b/src/main/java/com/marklogic/mapreduce/ContentOutputFormat.java index b51836925..08bb16bd2 100644 --- a/src/main/java/com/marklogic/mapreduce/ContentOutputFormat.java +++ b/src/main/java/com/marklogic/mapreduce/ContentOutputFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2024 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. + * Copyright (c) 2011-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -404,114 +404,120 @@ protected boolean initialize(Session session, boolean restrictHosts, if (LOG.isDebugEnabled()) { LOG.debug("init query: \n" + query.getQuery()); } - result = session.submitRequest(query); + try { + result = session.submitRequest(query); - if (!result.hasNext()) { - throw new IOException("Unexpected response"); - } - ResultItem item = result.next(); - boolean httpForwardHeaderExists; - boolean xdbcForwardHeaderExists; - if (getForwardHeader) { - httpForwardHeaderExists = item.asString().equals("true"); - if (!result.hasNext()) { - throw new IOException("Unexpected response"); - } - item = result.next(); - xdbcForwardHeaderExists = item.asString().equals("true"); if (!result.hasNext()) { throw new IOException("Unexpected response"); } - item = result.next(); - if (httpForwardHeaderExists || xdbcForwardHeaderExists) { - restrictHosts = true; - conf.setBoolean(OUTPUT_RESTRICT_HOSTS, true); - if (LOG.isDebugEnabled()) { - LOG.debug("HTTP compliant mode enabled since x-forwarded-for exists"); + ResultItem item = result.next(); + boolean httpForwardHeaderExists; + boolean xdbcForwardHeaderExists; + if (getForwardHeader) { + httpForwardHeaderExists = item.asString().equals("true"); + if (!result.hasNext()) { + throw new IOException("Unexpected response"); } - } 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); + item = result.next(); + xdbcForwardHeaderExists = item.asString().equals("true"); + if (!result.hasNext()) { + throw new IOException("Unexpected response"); + } + item = result.next(); + if (httpForwardHeaderExists || xdbcForwardHeaderExists) { + restrictHosts = true; + conf.setBoolean(OUTPUT_RESTRICT_HOSTS, true); if (LOG.isDebugEnabled()) { - LOG.debug("HTTP compliant mode disabled since x-forwarded-for doesn't exist"); + LOG.debug("HTTP compliant mode enabled since x-forwarded-for exists"); + } + } 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"); + } } } } - } - initHostName = item.asString(); - if (!result.hasNext()) { - throw new IOException("Unexpected response"); - } - item = result.next(); - am.setEffectiveVersion(((XSInteger)item.getItem()).asLong()); - if (!result.hasNext()) { - throw new IOException("Unexpected response"); - } - item = result.next(); - failover = !restrictHosts && item.asString().equals("true"); - if (!result.hasNext()) { - throw new IOException("Unexpected response"); - } - item = result.next(); - supportSegment = item.asString().equals("true"); - if (result.hasNext()) { + initHostName = item.asString(); + if (!result.hasNext()) { + throw new IOException("Unexpected response"); + } item = result.next(); - String policyStr = item.asString(); - conf.set(ASSIGNMENT_POLICY, policyStr); - policy = AssignmentPolicy.Kind.forName(policyStr); + am.setEffectiveVersion(((XSInteger)item.getItem()).asLong()); if (!result.hasNext()) { throw new IOException("Unexpected response"); } item = result.next(); - allowFastLoad = Boolean.parseBoolean(item.asString()); - if ((policy == AssignmentPolicy.Kind.STATISTICAL - || policy == AssignmentPolicy.Kind.RANGE - || policy == AssignmentPolicy.Kind.QUERY) - && !allowFastLoad && conf.getBoolean(OUTPUT_FAST_LOAD, false)) { - throw new IOException( - "Fastload can't be used: rebalancer is on and " - + "forests are imbalanced in a database with " - + "statistics-based assignment policy"); + failover = !restrictHosts && item.asString().equals("true"); + if (!result.hasNext()) { + throw new IOException("Unexpected response"); } - } else { - policy = AssignmentPolicy.Kind.LEGACY; - legacy = true; - } - - // 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; + item = result.next(); + supportSegment = item.asString().equals("true"); + if (result.hasNext()) { + item = result.next(); + String policyStr = item.asString(); + conf.set(ASSIGNMENT_POLICY, policyStr); + policy = AssignmentPolicy.Kind.forName(policyStr); + if (!result.hasNext()) { + throw new IOException("Unexpected response"); + } + item = result.next(); + allowFastLoad = Boolean.parseBoolean(item.asString()); + if ((policy == AssignmentPolicy.Kind.STATISTICAL + || policy == AssignmentPolicy.Kind.RANGE + || policy == AssignmentPolicy.Kind.QUERY) + && !allowFastLoad && conf.getBoolean(OUTPUT_FAST_LOAD, false)) { + throw new IOException( + "Fastload can't be used: rebalancer is on and " + + "forests are imbalanced in a database with " + + "statistics-based assignment policy"); + } + } else { + policy = AssignmentPolicy.Kind.LEGACY; + legacy = true; + } + + // 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; } } else { - //neither fastload nor output_dir is set - fastLoad = false; + fastLoad = conf.getBoolean(OUTPUT_FAST_LOAD, false); + if (fastLoad && conf.get(OUTPUT_PARTITION) == null + && (policy == AssignmentPolicy.Kind.RANGE || + policy == AssignmentPolicy.Kind.QUERY)) { + throw new IllegalArgumentException( + "output_partition is required for fastload mode."); + } } - } else { - fastLoad = conf.getBoolean(OUTPUT_FAST_LOAD, false); - if (fastLoad && conf.get(OUTPUT_PARTITION) == null - && (policy == AssignmentPolicy.Kind.RANGE || - policy == AssignmentPolicy.Kind.QUERY)) { - throw new IllegalArgumentException( - "output_partition is required for fastload mode."); + conf.setBoolean(OUTPUT_FAST_LOAD, fastLoad); + return restrictHosts; + } finally { + if (result != null) { + result.close(); } } - conf.setBoolean(OUTPUT_FAST_LOAD, fastLoad); - return restrictHosts; } /**