97 lines
2.6 KiB
Plaintext
97 lines
2.6 KiB
Plaintext
Having a <code>switch</code> and its cases wholly encompassed by a control structure such as a <code>try</code>, <code>@try</code>, <code>catch</code>, <code>@catch</code>, or a loop is perfectly acceptable. (<code>try</code> and <code>catch</code> are used hereafter to refer to both variants.) It is also acceptable to have a <code>goto</code> and its target label wholly encompassed in a control structure.
|
|
|
|
What is not acceptable is using a <code>goto</code> or <code>case</code> to suddenly jump into the body of a <code>try</code>, <code>catch</code>, Objective-C <code>@finally</code>, or loop structure. Tangling labels or <code>switch</code> blocks with other control structures results in code that is difficult, if not impossible to understand. More importantly, when it compiles (some of these constructs won't compile under ISO-conformant compilers), it can lead to unexpected results. Therefore this usage should be strictly avoided.
|
|
|
|
This C++ code sample, which is also applicable to Objective-C if <code>try</code> and <code>catch</code> are converted to <code>@try</code> and <code>@catch</code>, demonstrates jumping into a <code>switch</code> and into a <code>try</code> and <code>catch</code> :
|
|
|
|
|
|
== Noncompliant Code Example
|
|
|
|
----
|
|
void f ( int32_t i )
|
|
{
|
|
if ( 10 == i )
|
|
{
|
|
goto Label_10; // Noncompliant; goto transfers control into try block
|
|
}
|
|
|
|
if ( 11 == i )
|
|
{
|
|
goto Label_11; // Noncompliant; goto transfers control into catch block
|
|
}
|
|
|
|
switch ( i )
|
|
{
|
|
case 1:
|
|
try
|
|
{
|
|
Label_10:
|
|
case 2: // Noncompliant; switch transfers control into try block
|
|
// Action
|
|
break;
|
|
}
|
|
catch ( ... )
|
|
{
|
|
Label_11:
|
|
case 3: // Noncompliant; switch transfers control into catch block
|
|
// Action
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
// Default Action
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
----
|
|
|
|
|
|
== Compliant Solution
|
|
|
|
----
|
|
void f ( int32_t i )
|
|
{
|
|
switch ( i )
|
|
{
|
|
case 1:
|
|
case 2:
|
|
// Action
|
|
break;
|
|
case 3:
|
|
// Action
|
|
break;
|
|
case 10:
|
|
|
|
default:
|
|
{
|
|
// Default Action
|
|
break;
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
if ( 2 == i || 10 == i)
|
|
{
|
|
// Action
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
if (3 == i || 11 == i)
|
|
{
|
|
// Action
|
|
}
|
|
}
|
|
}
|
|
----
|
|
|
|
|
|
== See
|
|
|
|
* MISRA C++:2008, 15-0-3 - Control shall not be transferred into a try or catch block using goto or switch statement
|
|
* https://www.securecoding.cert.org/confluence/x/DgDFAQ[CERT, MSC20-C.] - Do not use a switch statement to transfer control into a complex block
|
|
|