]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Ensure ACLChecklist::markFinished() is called (#1809)
authorEduard Bagdasaryan <eduard.bagdasaryan@measurement-factory.com>
Wed, 15 May 2024 22:30:07 +0000 (22:30 +0000)
committerSquid Anubis <squid-anubis@squid-cache.org>
Thu, 16 May 2024 04:53:44 +0000 (04:53 +0000)
For example, ACLChecklist::resumeNonBlockingCheck() missed a
markFinished() call when prepNonBlocking() returned false after a
reconfiguration. Missing markFinished() calls result in the last
evaluated ACL name being unset in nonBlockingCheck() callbacks.

src/acl/Checklist.cc
src/acl/Checklist.h

index c04014500cbf9173f0ce1b0bd149766ca52a230a..4dc5ad7e396f98753d8dd94ee93873213ed209fe 100644 (file)
@@ -23,7 +23,7 @@ ACLChecklist::prepNonBlocking()
     assert(accessList);
 
     if (callerGone()) {
-        checkCallback(ACCESS_DUNNO); // the answer does not really matter
+        checkCallback("caller is gone"); // the answer does not really matter
         return false;
     }
 
@@ -34,8 +34,7 @@ ACLChecklist::prepNonBlocking()
 
     if (!cbdataReferenceValid(accessList)) {
         cbdataReferenceDone(accessList);
-        debugs(28, 4, "ACLChecklist::check: " << this << " accessList is invalid");
-        checkCallback(ACCESS_DUNNO);
+        checkCallback("accessList is invalid");
         return false;
     }
 
@@ -51,7 +50,7 @@ ACLChecklist::completeNonBlocking()
         calcImplicitAnswer();
 
     cbdataReferenceDone(accessList);
-    checkCallback(currentAnswer());
+    checkCallback(nullptr);
 }
 
 void
@@ -155,17 +154,20 @@ ACLChecklist::goAsync(AsyncStarter starter, const Acl::Node &acl)
 // ACLFilledChecklist overwrites this to unclock something before we
 // "delete this"
 void
-ACLChecklist::checkCallback(const Acl::Answer &answer)
+ACLChecklist::checkCallback(const char * const abortReason)
 {
+    if (abortReason)
+        markFinished(ACCESS_DUNNO, abortReason);
+    Assure(finished());
+
     ACLCB *callback_;
     void *cbdata_;
-    debugs(28, 3, "ACLChecklist::checkCallback: " << this << " answer=" << answer);
 
     callback_ = callback;
     callback = nullptr;
 
     if (cbdataReferenceValidDone(callback_data, &cbdata_))
-        callback_(answer, cbdata_);
+        callback_(currentAnswer(), cbdata_);
 
     // not really meaningful just before delete, but here for completeness sake
     occupied_ = false;
@@ -213,7 +215,7 @@ ACLChecklist::nonBlockingCheck(ACLCB * callback_, void *callback_data_)
      * We cannot select a sensible default for all callers here. */
     if (accessList == nullptr) {
         debugs(28, DBG_CRITICAL, "SECURITY ERROR: ACL " << this << " checked with nothing to match against!!");
-        checkCallback(ACCESS_DUNNO);
+        checkCallback("nonBlockingCheck() without accessList");
         return;
     }
 
index 3f7fcd96bf4f4282e87aa3590af8f935698cabcf..108999169487c4d3d88add94b79b64fa0b30a517 100644 (file)
@@ -159,7 +159,8 @@ public:
 
 private:
     /// Calls non-blocking check callback with the answer and destroys self.
-    void checkCallback(const Acl::Answer &answer);
+    /// If abortReason is provided, sets the final answer to ACCESS_DUNNO.
+    void checkCallback(const char *abortReason);
 
     void matchAndFinish();