JavaScript is not currently enabled, but is required for full CodeSonar manual search and browse functionality.

If you are viewing this file in your hub's Web GUI, enable JavaScript in your browser: you will also need it for GUI functionality.

If you opened this file directly from disk, your browser may be directly suppressing JavaScript functionality: certain browsers perform this suppression on local files (but not files delivered by web servers) for security reasons.

CodeSonar® 9.2p0 CONFIDENTIAL CodeSecure Inc
C#


CSHARP.CONCURRENCY.UG.PARAM : Unguarded Parameter (C#)

Summary

A parameter of a method or constructor is accessed without the expected lock being held.

C# uses statements and methods to guarantee thatdata is accessed in a sequential way and avoid race conditions in multithreaded applications. This is achieved with the lock statements, or by surrounding a block between calls to Monitor.Enter(obj) and Monitor.Exit(obj). Incorrect uses of synchronization result in unexpected behaviors and subtle bugs, very hard to identify and reproduce. This checker helps the programmer by identifying or checking the locks that are held when a field is accessed or a method is called. This information can be inferred, and reported in a jaif file, or verified, if the programmer provides source code attributes on the locks that must be held for specific fields and methods. Moreover, this checker signals situations where a synchronization seems missing on a field.

The [GuardedBy] attribute for fields and parameters and the [Holding] attribute for methods and constructors accepts a string argument, according to the following syntax

Properties

Class Name Unguarded Parameter (C#)
Significance reliability
Mnemonic CSHARP.CONCURRENCY.UG.PARAM
Categories
CWE CWE:567 Unsynchronized Access to Shared Data in a Multithreaded Context
Availability Available for C# only.
Enabling Checks for this warning class are disabled by default. To enable them, add the following WARNING_FILTER rule to the project configuration file.
WARNING_FILTER += allow class="Unguarded Parameter (C#)"

Example

Suppose we are analyzing the following code, and have set CSHARP_ANALYSIS_ENTRY_POINTS_MODE=LIBRARY in the project configuration file.

using System;
using System.Runtime.CompilerServices;
using com.juliasoft.julia.checkers.guardedBy;

namespace GuardedByTest 
{
  public class GuardedByTest
    {
        [GuardedBy(new string[] { "lock1" })] private int counter;
        private object lock1 = new object();
        private long counter2;
        private static int counter3;
        private static object lock4 = new object();
        private static int counter4 = 13;
        private readonly object[] locks = new object[10];
        private int next;
        private readonly object lock5 = new object();
        private static readonly object lock6 = new object();
        private int counter5;
        public GuardedByTest()
        {
            counter = 1;
            counter5 = 17;
            counter5 += counter;
        }
        [MethodImpl(MethodImplOptions.Synchronized)]
        public void IncrementCounter()
        {
            counter++;
        }
        public void DecrementCounter()
        {
            lock (this)
            {
                counter--;
            }
        }
        public bool CheckCounterIs0()
        {
            object copy = this;
            lock (copy)
            {
                return counter == 0;
            }
        }
        public void IncrementOtherCounter(GuardedByTest other)
        {
            GuardedByTest copy = other;
            lock (copy)
            {
                IncrementCounterAux(other);
            }
        }
        private void IncrementCounterAux([GuardedBy(new string[] { "this" })] GuardedByTest other) // "Unguarded Parameter (C#)" warning issued here
                                                                                                   // - [GuardedBy] annotation differs from that inferred, as discussed below
        {
            other.counter += 2;
        }
        public void IncrementCounter2()
        {
            lock (lock1)
            {
                counter2++;
            }
        }
        public void DecrementCounter2()
        {
            lock (lock1)
            {
                counter2--;
            }
        }
        public bool CheckCounter2Is0()
        {
            object copy = lock1;
            lock (copy)
            {
                return counter2 == 0;
            }
        }
        public void IncrementOtherCounter2(GuardedByTest other)
        {
            GuardedByTest copy = other;
            lock (copy.lock1)
            {
                IncrementCounter2Aux(other);
            }
        }
        private static void IncrementCounter2Aux(GuardedByTest other)
        {
            other.counter2 += 2;
        }
        public void IncrementCounter3()
        {
            lock (typeof(GuardedByTest))
            {
                counter3++;
            }
        }
        [Holding(new string[] { "GuardedByTest.class" })]
        [MethodImpl(MethodImplOptions.Synchronized)]
        public static void DecrementCounter3()
        { // UnguardedMethodOrConstructorWarning
            counter3--;
        }
        public void IncrementCounter4()
        {
            lock (lock4)
            {
                counter4++;
            }
        }
        public static void DecrementCounter4()
        {
            lock (lock4)
            {
                DecrementCounter4Aux();
            }
        }
        [Holding(new string[] { "GuardedByTest.lock4" })]
        private static void DecrementCounter4Aux()
        {
            counter4--;
        }
        private object GetLock()
        {
            return locks[next % locks.Length];
        }
        public void IncrementCounter5()
        {
            lock (GetLock())
            {
                counter5++;
                next++;
            }
        }
        public void DecrementCounter5()
        {
            lock (GetLock())
            {
                DecrementCounter5Aux();
            }
        }
        private void DecrementCounter5Aux()
        {
            counter5--;
        }
        public void AccessLock5()
        {
            lock (lock5)
            {
                lock5.GetHashCode();
            }
        }
        public static void AccessLock6()
        {
            lock (lock6)
            {
                lock6.GetHashCode();
            }
        }
        [MethodImpl(MethodImplOptions.Synchronized)]
        public void ParameterTest1(object o1, string o2, string o3)
        {
            Console.WriteLine(o1);
            lock (lock1)
            {
                Console.WriteLine(o2);
            }
            lock (o3)
            {
                Console.WriteLine(o3 + " ");
            }
        }
    }
}

CodeSonar will infer the following @GuardedBy and @Holding annotations for class GuardedBy.

    field counter:
      type: @GuardedBy("this")
    field counter2:
      type: @GuardedBy("lock")
    field counter3:
      type: @GuardedBy("GuardedByTest.class")
    field counter4:
      type: @GuardedBy("GuardedByTest.lock4")
    field counter5:
      type: @GuardedBy("getLock()")
    field lock5:
      type: @GuardedBy("itself")
    field lock6:
      type: @GuardedBy("itself")
    method DecrementCounter()V:
      receiver: @GuardedBy("itself")
    method DecrementCounter3()V:
    method DecrementCounter4Aux()V: @Holding("GuardedByTest.lock4")
    method DecrementCounter5Aux()V: @Holding("getLock()")
      receiver: @GuardedBy("getLock()")
    method IncrementCounter()V:
      receiver: @GuardedBy("itself")
    method IncrementCounterAux(LGuardedByTest;)V:
      parameter #0:
        type: @GuardedBy("itself")
    method ParameterTest1(LSystem.Object;LSystem.String;LSystem.String;)V:
      receiver: @GuardedBy("itself")
      parameter #0:
        type: @GuardedBy("this")
      parameter #1:
        type: @GuardedBy("lock") @GuardedBy("this")
      parameter #2:
        type: @GuardedBy("itself") @GuardedBy("this")

Resolution

Verify if the missing synchronization should actually be there. Annotate fields and methods with the lock that must be held when they are accessed or called, by using the @GuardedBy and @Holding annotations. If this checker does not accept those annotations, it is likely the case that your program has a synchronization problem.

Relevant Configuration File Parameters

The following configuration file parameters affect checks for this warning class.

 

To report problems with this documentation, please visit https://support.codesecure.com/.