If without else statement?

There are situations where I could use if statement without else?

Like this one: https://eslint.org/docs/rules/no-else-return

or

this: https://rules.sonarsource.com/java/RSPEC-126

The research is clear, is always possible and better to consider all possible scenarios and strive for perfect clarity:

https://wiki.sei.cmu.edu/confluence/display/c/MSC01-C.+Strive+for+logical+completeness

CMU is talking about an else after else if condition, just like https://rules.sonarsource.com/java/RSPEC-126 mention.

But what happens with https://eslint.org/docs/rules/no-else-return?

We need to decide what source is more authoritative, and I think CMU is better than eslint. In any case, this rule only suggests that:


function foo() {

int ret = 0;
    if (x) {
        ret = 1;
    } else {
        ret = 2;
    }

return ret;

}

Regaring else-if only situation, just check the approach of CMU in the case of switch, always requiring a default scenario.

I’ve reading lots of sites and the general consensus is that an else after an if is not required and it’s even discouraged when the logic allows it due to branch predictions and because the resultant compiled code is more complex and it’s only proposed when you use if-elseif situations. Even then; it is better to replace an if-elsif-else with a switch statement.

I think it’s a good idea to treat each case (if without else) individually and not as a pattern to report a finding when it’s not present.

  • What is your personal opinion independent of other documentations?
  • What do you think about this?

https://fsharpforfunandprofit.com/posts/expressions-vs-statements/

  • Why in our products we don’t have problems with this rule?

I personally think that the else statement is an optional statement. It doesn’t always need to be declared in code. In the source you quoted the security weakness in the example code may be caused by the lack of initialization of the variable, not the lack or the presence of the else statement.

Think about this code:

account_number = get_account_number()
if (account_number.startswith('5')):
     apply_special_bussiness_rule_to_accounts_started_with_5(account_number)
cancel_account(account_number)

In that case, an else is unnecessary because only accounts started with 5 will need special treatment, and then the account is canceled, whether it started with 5 or not.

Another example (quoted from a source I gave before)

if (car.tank.empty())
{
 gas_station.fill_gas(car);
}
car.go_to("ExitoEnvigado");

The car will only need to fill gas if the tank is empty, and in any case the car must go to Exito Envigado.

An else statement in those examples will be useless and if stated will be empty.

That’s why I think that every if-else must be reviewed manually and that lack of an else should not be used as a pattern to report a security finding.

Then we should remove from asserts or just try to only allow if-without-else in guard clauses.

https://en.wikipedia.org/wiki/Guard_(computer_science)

Seems that as a Guard is valid, or as a sequence of guards.

1 Like

There are methods in Asserts that exists to check for the vulnerability when it applies (in fact, all of them)

It’s not like if the check exists then I’ll run it against everything

Just to mention two examples: missing Cache-Control and Pragma headers, they only apply to content with sensitive information, there is no problem in caching public content. So, it’s up to the analyst who writes the exploit to use the check in the right way against the right URLs using the right HTTP Verb when the vulnerability applies

Following that logic, there are situations where having the method to check for the if without else can be handful and I don’t think we should remove it from the product

However, the methods in Asserts SAST are different from DAST methods. In SAST the searching capabilities (directory, files, etc.) allows or even induce to use it for finding AND check. In DAST there is implicit protection because we don’t have crawler, fuzzing, capabilities in there. This is an accidental feature that makes your statement categorically different.

In other words, is there a method in asserts that breaks the build pointing to a specific instance (loc) that is confirmed that need an else?

I think that leaves this method opens big issues:

  • document how and when else is appropriate
  • automate for these scenarios
  • if the latter is not possible, the former will need long and detailed documentation and debate

Nice argument, I haven’t though about that

is there a method in asserts that breaks the build pointing to a specific instance (loc) that is confirmed that need an else?

There is not but we can:

Since specifying the line of occurrence for the if is subject to a lot of variability, I propose to identify ‘if’ statements by its condition, so:

condition: str = ‘1 == 2’ # some analyst supplied condition must match this in order to recognize the if

if (1 == 2) {}
will return OPEN

if (1 == 2) {} else {}
will return CLOSED

but

if (3 == 2) {}
will return CLOSED as de condition does not match

with this the method will not be open to the issues:

  • document how and when else is appropriate
  • automate for these scenarios

because with this param, the analyst is the one who supplies what ‘if’ or ‘ifs’ he/her is sure must have an else clause

So the location, in this case, will be the conditional expression, sounds great for me.

And finally, I found an appropriate and authoritative reference to support ALWAYS the use of default scenarios:

https://www.iso.org/standard/61457.html, ISO/IEC TR 24772:2013 Preview Information technology – Programming languages – Guidance to avoiding vulnerabilities in programming languages through language selection and use

D.30.2 Guidance to language users (paragraph 2)
Use a final else statement or a comment stating why the final else isn’t necessary in all if and else if statements

https://standards.iso.org/ittf/PubliclyAvailableStandards/index.html

Finally, there are languages in which ones if, switch, etc are expressions and not statements, and therefore forces to focus the code design in always returning a value, and in some situations (typed languages, typed linters) of the same type. In this kind of languages, the discussion is almost non-existent, and even less the apology of the shortness of code.

This leads to better design and explicitly handling all scenarios, avoid assumptions and not depend on the existence or presence of great programmers that are always outliers and not the common case.

https://www.us-cert.gov/bsi/articles/knowledge/principles/failing-securely

In fact, I think that the general recommendation of failing safe is better addressed explicitly and not leaving anything to interpretation. Even in obvious cases, I would recommend the use of assertion instead of a comment (invariant use of design by contract). Not only this recommendation is based on theory, but all of our codebases should also be in that way

https://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#usage-conditions

1 Like