Тестирование coreutils в защищённом режиме (обновляется)

Скомпилировать coreutils в защищённом режиме несложно:

./configure CFLAGS='-Wno-error=suggest-attribute=const -m128 -Wno-error=suggest-attribute=pure -Wno-error=suggest-attribute=noreturn -Wno-error=suggest-attribute=format -Wno-error=suggest-attribute=cold -Wno-error=suggest-attribute=malloc -Wno-error=bad-macro-redef -Wno-error=type-limits -Wno-error=shadow=global' LDFLAGS='-m128'

Изначально не проходит достаточно много тестов:

FAIL: tests/misc/help-version.sh
FAIL: tests/pr/pr-tests.pl
FAIL: tests/misc/date-debug.sh
FAIL: tests/misc/sort.pl
FAIL: tests/misc/sort-discrim.sh
FAIL: tests/misc/sort-month.sh
FAIL: tests/misc/sort-rand.sh
FAIL: tests/misc/yes.sh
FAIL: tests/du/long-from-unreadable.sh
FAIL: tests/rmdir/symlink-errors.sh

В тесте help-version.sh на самом деле вся проблема в программе shuf - она попросту не запускается.

Проблема - в создании неинициализированного блока памяти в lib/randread.c

static struct randread_source *
simple_new (FILE *source, void const *handler_arg)
{
  struct randread_source *s = xmalloc (sizeof *s);
  s->source = source;
  s->handler = randread_error;
  s->handler_arg = handler_arg;
  return s;
}

(дальше s->buf используется в lib/rand-isaac.c, ISAAC_MIX как переменная seed):

/* The basic ISAAC initialization pass.  */
#define ISAAC_MIX(s, a, b, c, d, e, f, g, h, seed) \
  {                                                \
    int i;                                         \
                                                   \
    for (i = 0; i < ISAAC_WORDS; i += 8)           \
      {                                            \
        a += seed[i];                              \
        b += seed[i + 1];                          \
        c += seed[i + 2];                          \
        d += seed[i + 3];                          \
        e += seed[i + 4];                          \
        f += seed[i + 5];                          \
        g += seed[i + 6];                          \
        h += seed[i + 7];                          \
        mix (a, b, c, d, e, f, g, h);              \
        s->m[i] = a;                               \
        s->m[i + 1] = b;                           \
        s->m[i + 2] = c;                           \
        s->m[i + 3] = d;                           \
        s->m[i + 4] = e;                           \
        s->m[i + 5] = f;                           \
        s->m[i + 6] = g;                           \
        s->m[i + 7] = h;                           \
      }                                            \
  }

Решение очевидно и корректно - очищаем память после создания.

static struct randread_source *
simple_new (FILE *source, void const *handler_arg)
{
  struct randread_source *s = xmalloc (sizeof *s);
  memset(s, 0, sizeof *s);
  s->source = source;
  s->handler = randread_error;
  s->handler_arg = handler_arg;
  return s;
}

Программа shuf теперь работает. Новый список невыполненных тестов стал существенно короче:

FAIL: tests/pr/pr-tests.pl
FAIL: tests/misc/date-debug.sh
FAIL: tests/misc/tac.pl
FAIL: tests/misc/yes.sh
FAIL: tests/du/long-from-unreadable.sh
FAIL: tests/rmdir/symlink-errors.sh

Следующей исправим программу уes

Она полагается на весьма вольное допущение о том, что элементы, переданные в argv, следуют одним блоком памяти, один за другим (хотя на самом деле это массив указателей на указатели и не более того). Но проверяют это в строчках

do
    {
      size_t operand_len = strlen (*operandp);
      bufalloc += operand_len + 1;
      if (operandp + 1 < operand_lim
          && *operandp + operand_len + 1 != operandp[1])
        reuse_operand_strings = false;
    }
  while (++operandp < operand_lim);

Тут (в обычном режиме), если указатели расположены не единым блоком, то данная оптимизация отключается. В защищённом режиме это всё не работает, потому что за границы указателя выходить нельзя ни при каких условиях.

Добавляем специальный код для защищённого режима E2K

#ifdef __e2k__
  if (sizeof(void*) == 16) 
    { // in protected mode, pointers are 128-bit
      reuse_operand_strings = false;
    }
  #endif

Новый список невыполненных тестов:

FAIL: tests/pr/pr-tests.pl
FAIL: tests/misc/date-debug.sh
FAIL: tests/misc/tac.pl
FAIL: tests/misc/tac-2-nonseekable.sh
FAIL: tests/du/long-from-unreadable.sh
FAIL: tests/rmdir/symlink-errors.sh

Теперь появился новый сбойнувший тест tac, который, видимо, зависел от работы yes.