Невозможно передать нулевой байт аргументу программы, используя bash или любую другую оболочку.Это просто потому, что это невозможно в стандарте C.
Стандарт C гласит: C11 5.1.2.2.1p2 (выделено мной):
..параметры главной функции должны соответствовать следующим ограничениям:
- ...
- Если значение argc больше нуля, элементы массива от argv [0] до argv [argc-1] включительно должнысодержат указатели на строки , которые задаются значениями, определяемыми реализацией средой хоста до запуска программы....
- ...
"Строка" - это C11 7.1.1p1 (выделено мной):
Строкаявляется непрерывной последовательностью символов , оканчивающейся на и включающей в себя первый нулевой символ.... Длина строки - это число байтов, предшествующих нулевому символу, а значение строки - это последовательность значений содержащихся символов в порядке.
«Нулевой символ»"является byte with all bits set to 0
C11 5.2.1p2 .Это ноль.На первом «нулевом символе» строка заканчивается.Если массив символов содержит ноль байтов, он не может быть строкой (хех, в точном смысле см. note 78 , строковый литерал не может быть строкой, потому что он может содержатьнулевые символы).Вы не можете передавать несколько 0x00
значений, встроенных в аргументы, в программу на Си, поскольку это не будет передаваемой вами "строкой".
Правильный способ написать собственный синтаксический анализатор,будет принимать "строки" (т.е. ./a.out "00 2C 00 21"
) и конвертировать в ноль байтов самостоятельно.
Для вашего случая использования, если это просто, я мог бы представить более простой анализатор, чем в другом ответе.Вы могли бы бывшийпередайте аргумент со всеми байтами, увеличенными на 1, затем уменьшите на 1 в вашей программе.
Или вы можете передать специальное байтовое значение, например, ex.0xff
(если ваша реализация, операционная система и среда поддерживают передачу 0xff
байтов) вместо 0x00
и замените их в вашей программе.Эта опция представлена ниже:
#include <string.h>
#include <stddef.h>
#include <assert.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
assert(argc >= 2);
for (size_t i = 0, max = strlen(argv[1]); i < max; ++i) {
// replace all 0xff by 0x00
if ( (0xff & argv[1][i]) == 0xff) {
argv[1][i] = 0x00;
}
}
// use argv[1]
for (size_t i = 0, max = 4; i < max; ++i) {
printf("argv[1][%d] = 0x%02x\n", i, 0xff & argv[1][i]);
}
}
и вызов с:
./a.out $'\xff\x2c\xff\x2c'
Проверено на repl.it .
$'...'
bash интерпретируется как ANSI-C Цитирование .\xff
интерпретируются как шестнадцатеричные константы, поэтому первый аргумент будет равен (char[]){0xff, 0x2c, 0xff, 0x2c, 0x00}
.После замены 0xff
на 0x00
оно станет (char[]){0x00, 0x2c, 0x00, 0x2c, 0x00}
, и вы сможете использовать первые 4 байта.