Kann Argc überlaufen?

75

Ich war in SO unterwegs und habe diese Frage gesehen . Dann begann ich mich zu fragen, ob ich argc überlaufen kann.

Standard sagt, dass argv[argc]dies ein Nullzeiger sein muss, aber dies ist falsch, wenn argc überläuft.

(I schrieb ein kleines C - Programm und einen Python - Skript , es zu testen , sondern ein bekommt MemoryError.)

Vielen Dank!


Begründung für den internationalen Standard - Programmiersprachen - C §5.1.2.2.1 Programmstart

Die Spezifikation von argcund argvals Argumente zur mainAnerkennung umfangreicher früherer Praktiken. argv[argc]muss ein Nullzeiger sein, um eine redundante Prüfung für das Ende der Liste bereitzustellen, auch auf der Grundlage der gängigen Praxis.

Bora M. Alper
quelle
13
Standard says that argv[argc] must be a null pointer but this will be false if argc overflow - Ich habe dies als "Lass Argc nicht überlaufen" gelesen. ("Doktor, es tut weh, wenn ich das tue")
Robert Harvey
4
Unter POSIX und auf den meisten Linux-Systemen ist der anfängliche Stapel von main-as, der von execve- einschließlich seiner Argumente (dh argv) installiert wurde , viel eingeschränkter (normalerweise einige Megabyte). Also argcist weniger als ein paar Millionen und ich habe noch nie von einem Betriebssystem gehört, das in argcder Nähe sein könnteINT_MAX
Basile Starynkevitch
6
Wahrscheinlich wird die Implementierung in einem solchen Fall eine systemspezifische Grenze haben, die es unmöglich macht, 2 ^ 15 Argumente an ein Programm zu übergeben
Nr.
14
Nun, ich schreibe sie bestimmt nicht ein :)
Martin James
3
Moment mal, was meine ich mit "Ich wäre nicht überrascht". Jede LP64- oder LLP64-Architektur ist genau das Richtige, also Windows oder Linux. Sie würden jedoch viel RAM benötigen. Ich nehme an, wenn Sie von vorne anfangen, argcsollten Sie Typ haben size_t.
Steve Jessop

Antworten:

78

Nach dem Standard

Also, aus Ihrem Zitat:

argv[argc] muss ein Nullzeiger sein

Daher argckann nicht überlaufen, weil dann die obige Aussage würde nicht wahr sein.

In der Praxis

In der Praxis ist die Gesamtgröße der an ein Programm übergebenen Argumente begrenzt.

Auf meinem Linux / x64-System:

$ getconf ARG_MAX
2097152

Daher beträgt die Gesamtargumentgröße etwa 2 Megabyte und argckann nicht überlaufen. Ich glaube, diese Grenze misst eine Kombination der Gesamtdaten in argvund der Umgebung. Wenn Sie diese Grenze überschreiten, wenn Sie versuchen, einen Befehl auszuführen, exec()schlägt dies fehl E2BIG. Von man 2 execve:

E2BIG Die Gesamtzahl der Bytes in der Umgebung (envp) und im Argument
       list (argv) ist zu groß.

Ich glaube, dass die ~ 2-Megabyte-Grenze auf meinem System im Vergleich zu anderen Systemen relativ großzügig ist. Mein OS X-System meldet ein Limit von ~ 260 KB.

Aber was wäre, wenn ARG_MAXsie wirklich groß wären ?

Okay, nehmen wir an, Sie befinden sich auf einem alten / seltsamen System, also int16 Bit, und ARG_MAX liegt weit über 2 15 , was ansonsten durchaus vernünftig ist. Angenommen, Sie rufen execve()mit mehr als 2 bis 15 Argumenten auf. Die Implementierung hat zwei Möglichkeiten.

  1. Es kann argczu einem Überlauf kommen ... im Grunde genommen können Sie Ihre Daten wegwerfen, sicherstellen, dass das von Ihnen ausgeführte Programm auf unerwartete und wahrscheinlich fehlerhafte Weise ausgeführt wird, und gegen den C-Standard verstoßen. Am schlimmsten ist, dass der Fehler still ist, sodass Sie es möglicherweise nie erfahren.

  2. Oder es kann einfach Rückkehr EOVERFLOWaus execve(), die Sie darüber informiert , dass es einfach nicht , ein Bild mit , dass viele Parameter ausführen. Nun, die POSIX / SUS-Standards erwähnen nichts über dieses Fehlerergebnis ... aber ich vermute, das liegt einfach daran, dass die Standardschreiber nie erwartet haben ARG_MAX, größer als zu sein INT_MAX.

Option 2 ist die einzig vernünftige Option. Wenn Ihr System irgendwie Option 1 wählt, ist diese defekt und Sie sollten einen Fehlerbericht einreichen.

Alternativ könnten Sie versuchen, ein altes Programm auszuführen, das für ein 16-Bit-System kompiliert wurde, aber Sie führen es über eine Art Emulator oder Kompatibilitätsschicht aus. Ich würde erwarten, dass der Emulator oder die Kompatibilitätsschicht eine Fehlermeldung ausgibt, wenn Sie versuchen, mehr als 2 15 Parameter an ein Programm zu übergeben.

Dietrich Epp
quelle
Aber stellen Sie sich vor, Sie befinden sich auf einem System, auf dem das ARG_MAX-Ding (aus welchen Gründen auch immer) ziemlich groß ist und es passieren könnte. Was für ein Fehler wäre das? Da der Standard immer noch eingehalten wird, kann er als C-kompatibel bezeichnet werden, es kann jedoch auch zu einem undefinierten Verhalten kommen, bei dem der Programmierer keine Option hat, dies zu verhindern. Was ist das für ein Fehler?
Dhein
Ich denke, der Standard hat dort ein undefiniertes Verhalten, da ein signierter Überlauf nicht definiert ist.
Sebastian Mach
1
@zaibis Die Anforderung argv[argc], ein Nullzeiger zu sein, impliziert die Anforderung, ARG_MAXklein genug zu setzen , argc damit kein Überlauf möglich ist.
zwol
17

In der Praxis können Sie nicht. Die meisten Systeme begrenzen die Gesamtgröße von argvund relativ niedrig envp. Grenzwerte zwischen zehn und Hunderten von KB sind keine Seltenheit. Unter http://www.in-ulm.de/~mascheck/various/argmax/ finden Sie eine einigermaßen umfassende Auflistung der Grenzwerte für verschiedene Betriebssysteme.

Dämmerung -inaktiv-
quelle
1
Diese Liste enthält keine Daten für Windows, aber es gibt Fragen zu SO mit einigen Zahlen.
PTwr
10

Ich habe es versucht:

test.c:

Dann benutzte ich eine große Zip-Datei

Lesen Sie dann die Datei als Parameter für das Testprogramm:

Ergebnis:

Dann habe ich eine kleinere Datei ausprobiert:

Und:

ehwas
quelle
2
Warum eine Zip-Datei verwenden, um Argumente zu generieren, wenn Sie nur $ (seq 1 100000) können?
Pflaquerre
Ich habe nicht daran gedacht. Vielen Dank!
Wie war der
2

Wie im Standard angegeben, muss argv [argc] ein gültiger Wert sein.

Befindet sich die Laufzeitumgebung in einer Situation, in der dies nicht garantiert werden kann, sollte das Programm nicht gestartet werden.

Yves Daoust
quelle