This is an automated email from the ASF dual-hosted git repository. anmolnar pushed a commit to branch branch-3.8 in repository https://gitbox.apache.org/repos/asf/zookeeper.git
commit 5f0f50a0d277666726d3a79f4eb19ccded2895f2 Author: Andor Molnar <[email protected]> AuthorDate: Thu Jul 9 12:27:13 2026 -0500 Missing ACL check in setWatches() on reconnect --- .../java/org/apache/zookeeper/server/DataTree.java | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/DataTree.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/DataTree.java index 81789d642..265c44e41 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/DataTree.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/DataTree.java @@ -1523,9 +1523,9 @@ public void setWatches(long relativeZxid, List<String> dataWatches, List<String> DataNode node = getNode(path); WatchedEvent e = null; if (node == null) { - watcher.process(new WatchedEvent(EventType.NodeDeleted, KeeperState.SyncConnected, path)); + processWatchEvent(watcher, new WatchedEvent(EventType.NodeDeleted, KeeperState.SyncConnected, path), null); } else if (node.stat.getMzxid() > relativeZxid) { - watcher.process(new WatchedEvent(EventType.NodeDataChanged, KeeperState.SyncConnected, path)); + processWatchEvent(watcher, new WatchedEvent(EventType.NodeDataChanged, KeeperState.SyncConnected, path), new ArrayList<>(getACL(node))); } else { this.dataWatches.addWatch(path, watcher); } @@ -1533,7 +1533,7 @@ public void setWatches(long relativeZxid, List<String> dataWatches, List<String> for (String path : existWatches) { DataNode node = getNode(path); if (node != null) { - watcher.process(new WatchedEvent(EventType.NodeCreated, KeeperState.SyncConnected, path)); + processWatchEvent(watcher, new WatchedEvent(EventType.NodeCreated, KeeperState.SyncConnected, path), new ArrayList<>(getACL(node))); } else { this.dataWatches.addWatch(path, watcher); } @@ -1541,9 +1541,9 @@ public void setWatches(long relativeZxid, List<String> dataWatches, List<String> for (String path : childWatches) { DataNode node = getNode(path); if (node == null) { - watcher.process(new WatchedEvent(EventType.NodeDeleted, KeeperState.SyncConnected, path)); + processWatchEvent(watcher, new WatchedEvent(EventType.NodeDeleted, KeeperState.SyncConnected, path), null); } else if (node.stat.getPzxid() > relativeZxid) { - watcher.process(new WatchedEvent(EventType.NodeChildrenChanged, KeeperState.SyncConnected, path)); + processWatchEvent(watcher, new WatchedEvent(EventType.NodeChildrenChanged, KeeperState.SyncConnected, path), new ArrayList<>(getACL(node))); } else { this.childWatches.addWatch(path, watcher); } @@ -1558,6 +1558,18 @@ public void setWatches(long relativeZxid, List<String> dataWatches, List<String> } } + /** + * Route replayed events through the ACL-aware overload so they get the same + * READ check as WatchManager.triggerWatch; acl is null for a deleted node. + */ + private void processWatchEvent(Watcher watcher, WatchedEvent event, List<ACL> acl) { + if (watcher instanceof ServerWatcher) { + ((ServerWatcher) watcher).process(event, acl); + } else { + watcher.process(event); + } + } + /** * This method sets the Cversion and Pzxid for the specified node to the * values passed as arguments. The values are modified only if newCversion
