# V612. Unconditional 'break/continue/return/goto' within a loop.

Анализатор обнаружил подозрительный цикл. В теле цикла используется один из следующих операторов: break, continue, return, goto. Эти операторы выполняются всегда, без каких либо условий.

Рассмотрим соответствующие примеры:

    do {
      X();
      break;
    } while (Foo();)

    for (i = 0; i < 10; i++) {
      continue;
      Foo();
    }

    for (i = 0; i < 10; i++) {
      x = x + 1;
      return;
    }

    while (*p != 0) {
      x += *p++;
      goto endloop;
    }
    endloop:

Показанные выше примеры циклов конечно искусственны и малоинтересны. Давайте рассмотрим фрагмент кода, найденный в одном из настоящих приложений. Для большей наглядности код функции сокращён.

    int DvdRead(....)
    {
      ....
      for (i=lsn; i<(lsn+sectors); i++){
        ....
    //    switch (mode->datapattern){
    //    case CdSecS2064:
          ((u32*)buf)[0] = i + 0x30000;
          memcpy_fast((u8*)buf+12, buff, 2048);
          buf = (char*)buf + 2064; break;
    //    default:
    //      return 0;
    //    }
      }
      ....
    }

Часть строк в функции закомментировано. Беда в том, что забыли закомментировать оператор "break".

Когда комментариев не было, "break" был внутри тела "switch". Когда "switch" закомментировали, оператор "break" стал досрочно завершать цикл. В результате тело цикла выполняется только один раз.

Корректный вариант кода:

    buf = (char*)buf + 2064; // break;

Следует отметить, что диагностическое правило V612 достаточно сложно. Учитывается множество ситуаций, когда использование оператора break/continue/return/goto совершенно корректно. Рассмотрим для примера несколько ситуаций, когда предупреждение V612 выводиться не будет.

1) Наличие условия.

    while (*p != 0) {
      if (Foo(p))
        break;
    }

2) Специальные приёмы, как правило, используемые в макросах:

    do { Foo(x); return 1; } while(0);

3) Обход оператора 'continue' с помощью 'goto':

    for (i = 0; i < 10; i++) {
      if (x == 7) goto skipcontinue;
      continue;
    skipcontinue: Foo(x);
    }

Возможны и другие приёмы, которые используются на практике, но про которые мы не знаем. Если вы заметили, что анализатор выдаёт ложное предупреждение V612, просим написать нам и прислать соответствующие примеры. Мы изучим их и постараемся реализовать исключения для подобных случаев.

Данная диагностика классифицируется как:

CWE-670 CERT-MSC01-C

Взгляните на примеры ошибок, обнаруженных с помощью диагностики V612.