Чи може argc переповнюватися?


75

Я блукав у СО і побачив це питання . Потім я почав гадати, чи можу я переповнити argc.

Стандарт говорить, що це argv[argc]повинен бути нульовий покажчик, але це буде хибним, якщо переповнення argc.

написав невелику програму на С та сценарій python для тестування, але отримав MemoryError.)

Дякую!


Обґрунтування міжнародного стандарту - Мови програмування - C § 5.1.2.2.1 Запуск програми

Специфікація argcта argvаргументи для mainвизнання великої попередньої практики. argv[argc]повинен бути нульовим покажчиком для забезпечення надмірної перевірки кінця списку, також на основі загальної практики.


13
Standard says that argv[argc] must be a null pointer but this will be false if argc overflow - Я читаю це як "Не дозволяйте argc переповнюватися". ("Докторе, боляче, коли я це роблю")
Роберт Харві,

4
У POSIX та в більшості систем Linux початковий стек main-як встановлений execve-, включаючи його аргументи (тобто argv), є набагато обмеженішим (зазвичай, кілька мегабайт). Отже argc, менше кількох мільйонів, і я ніколи не чув про ОС, де argcможе бути поручINT_MAX
Базиль Старинкевич

6
можливо, реалізація в такому випадку матиме специфічне для системи обмеження, що унеможливлює передачу 2 ^ 15 аргументів програмі

14
Ну, я точно їх не вводжу :)
Мартін Джеймс

3
Зачекайте секунду, що я маю на увазі "я б не здивувався". Будь-яка архітектура LP64 або LLP64 відповідає вимогам, тому Windows або Linux. Однак вам знадобиться багато оперативної пам'яті. Я вважаю, що якщо починати з нуля, argcповинен мати тип size_t.
Steve Jessop

Відповіді:


78

Відповідно до стандарту

Отже, з вашої цитати:

argv[argc] має бути нульовим покажчиком

Отже, argcне може переповнюватися, оскільки тоді вищезазначене твердження не було б істинним.

На практиці

На практиці загальний розмір аргументів, переданих програмі, обмежений.

У моїй системі Linux / x64:

$ getconf ARG_MAX
2097152

Отже, загальний розмір аргументу становить близько 2 мегабайт і argcне може переповнюватись. Я вважаю, що ця межа вимірює поєднання загальної суми даних argvта середовища. Якщо ви перевищите це обмеження під час спроби запустити команду, exec()помилка не відбудеться E2BIG. Від man 2 execve:

E2BIG Загальна кількість байтів у середовищі (envp) та аргумент
       список (argv) завеликий.

Я вважаю, що ліміт ~ 2 мегабайти в моїй системі є відносно щедрим порівняно з іншими системами. Моя система OS X повідомляє про обмеження ~ 260 КБ.

Але що, якби вони ARG_MAXбули справді великими?

Гаразд, припустимо, ви перебуваєте у старій / дивній системі, так intце 16 біт, а ARG_MAX значно перевищує 2 15 , що інакше цілком розумно. Тепер, припустимо, ви використовуєте execve()понад 2 15 аргументів. Реалізація має два варіанти.

  1. Це може дозволити argcпереповнення ... в основному, викидаючи ваші дані, гарантуючи, що програма, яку ви запускаєте, виконується якось несподівано і, можливо, помилково, і порушує стандарт C. Найгірше - помилка мовчить, тож ви ніколи не дізнаєтесь.

  2. Або він може просто повернутися EOVERFLOWз execve(), повідомляючи вам, що просто не може запустити зображення з такою кількістю параметрів. Зараз стандарти POSIX / SUS нічого не згадують про цей результат помилки ... але, я підозрюю, це просто тому, що стандартні автори ніколи не очікували, що ARG_MAXвони будуть більшими за INT_MAX.

Варіант №2 - єдиний розумний варіант. Якщо ваша система яким - то чином вибирає варіант # 1, то вона порушена , і ви повинні подати звіт про помилку.

Як варіант, ви можете спробувати запустити стару програму, скомпільовану для 16-розрядної системи, але ви запускаєте її через якийсь емулятор або рівень сумісності. Я б очікувати , що емулятор або сумісність шару буде видано повідомлення про помилку , якщо ви намагалися передати більше 2 15 параметрів програми.


Але уявіть, ви знаходитесь у системі, де ARG_MAX досить велика (з яких-небудь причин), і це може статися. Що це за провал? Оскільки він все ще дотримується стандарту, його можна назвати сумісним із С, але він також може спричинити невизначену поведінку, коли програміст не має можливості запобігти. Що це за помилка?
dhein

Я думаю, що Standard має невизначену поведінку, оскільки підписаний переповнення не визначений.
Себастьян Мах

1
@zaibis Вимога argv[argc]бути нульовим покажчиком передбачає вимогу встановити ARG_MAXдосить малий, який argc не може переповнюватися.
zwol

17

На практиці ні, ви не можете. Більшість систем встановлюють відносно низький ліміт на загальний комбінований розмір argvі envp. Обмеження в десятки - низькі сотні КБ - не рідкість; див. http://www.in-ulm.de/~mascheck/various/argmax/ щодо достатньо повного переліку обмежень для різних ОС.


1
У цьому списку немає даних для Windows, але є питання щодо SO з деякими цифрами.
PTwr

10

Я спробував це:

test.c:

Потім використав великий zip-файл

Потім прочитайте файл як параметри для тестової програми:

Результат:

Потім я спробував менший файл:

І:


2
Навіщо використовувати zip-файл для генерації аргументів, коли ви можете просто $ (seq 1 100000)?
pflaquerre

Не думав про це. Дякую!
ehwas

2

Як вказує стандарт, argv [argc] має бути дійсним значенням.

Отже, якщо середовище виконання знаходиться в такій ситуації, що воно не може цього гарантувати, воно не повинно запускати програму.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.