Procházet zdrojové kódy

Subscriptions: Fix false positives in clang-analyzer

Julius Pfrommer před 6 roky
rodič
revize
254dacfea4
1 změnil soubory, kde provedl 27 přidání a 3 odebrání
  1. 27 3
      src/server/ua_subscription_monitoreditem.c

+ 27 - 3
src/server/ua_subscription_monitoreditem.c

@@ -226,6 +226,12 @@ UA_MonitoredItem_delete(UA_Server *server, UA_MonitoredItem *monitoredItem) {
     UA_WorkQueue_enqueueDelayed(&server->workQueue, &monitoredItem->delayedFreePointers);
 }
 
+#ifdef __clang_analyzer__
+# define UA_CA_assert(clause) UA_assert(clause)
+#else
+# define UA_CA_assert(clause)
+#endif
+
 UA_StatusCode
 UA_MonitoredItem_ensureQueueSpace(UA_Server *server, UA_MonitoredItem *mon) {
     if(mon->queueSize - mon->eventOverflows <= mon->maxQueueSize)
@@ -233,6 +239,10 @@ UA_MonitoredItem_ensureQueueSpace(UA_Server *server, UA_MonitoredItem *mon) {
 
     /* Remove notifications until the queue size is reached */
     UA_Subscription *sub = mon->subscription;
+#ifdef __clang_analyzer__
+    UA_Notification *last = NULL;
+#endif
+
     while(mon->queueSize - mon->eventOverflows > mon->maxQueueSize) {
         /* At least two notifications that are not eventOverflows in the queue */
         UA_assert(mon->queueSize - mon->eventOverflows >= 2);
@@ -242,20 +252,27 @@ UA_MonitoredItem_ensureQueueSpace(UA_Server *server, UA_MonitoredItem *mon) {
         if(mon->discardOldest) {
             /* Remove the oldest */
             del = TAILQ_FIRST(&mon->queue);
+            UA_CA_assert(del != last);
 #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
-            while(UA_Notification_isOverflowEvent(server, del))
+            while(UA_Notification_isOverflowEvent(server, del)) {
                 del = TAILQ_NEXT(del, listEntry); /* skip overflow events */
+                UA_CA_assert(del != last);
+            }
 #endif
         } else {
             /* Remove the second newest (to keep the up-to-date notification) */
             del = TAILQ_LAST(&mon->queue, NotificationQueue);
             del = TAILQ_PREV(del, NotificationQueue, listEntry);
+            UA_CA_assert(del != last);
 #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
-            while(UA_Notification_isOverflowEvent(server, del))
+            while(UA_Notification_isOverflowEvent(server, del)) {
                 del = TAILQ_PREV(del, NotificationQueue, listEntry); /* skip overflow events */
+                UA_CA_assert(del != last);
+            }
 #endif
         }
-        UA_assert(del);
+
+        UA_assert(del && del->mon == mon);
 
         /* Move after_del right after del in the global queue. (It is already
          * right after del in the per-MonitoredItem queue.) This is required so
@@ -263,11 +280,16 @@ UA_MonitoredItem_ensureQueueSpace(UA_Server *server, UA_MonitoredItem *mon) {
          * always removing their first appearance in the gloal queue for the
          * Subscription. */
         UA_Notification *after_del = TAILQ_NEXT(del, listEntry);
+        UA_CA_assert(after_del != last);
         if(after_del) {
             TAILQ_REMOVE(&sub->notificationQueue, after_del, globalEntry);
             TAILQ_INSERT_AFTER(&sub->notificationQueue, del, after_del, globalEntry);
         }
 
+#ifdef __clang_analyzer__
+        last = del;
+#endif
+
         /* Delete the notification */
         UA_Notification_dequeue(server, del);
         UA_Notification_delete(del);
@@ -281,6 +303,7 @@ UA_MonitoredItem_ensureQueueSpace(UA_Server *server, UA_MonitoredItem *mon) {
     else
         indicator = TAILQ_LAST(&mon->queue, NotificationQueue);
     UA_assert(indicator);
+    UA_CA_assert(indicator != last);
 
     /* Create an overflow notification */
 #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
@@ -293,6 +316,7 @@ UA_MonitoredItem_ensureQueueSpace(UA_Server *server, UA_MonitoredItem *mon) {
             if(mon->discardOldest)
                 return UA_STATUSCODE_GOOD;
             UA_Notification *prev = TAILQ_PREV(indicator, NotificationQueue, listEntry);
+            UA_CA_assert(prev != last);
             if(prev && UA_Notification_isOverflowEvent(server, prev))
                 return UA_STATUSCODE_GOOD;
         }