Forum: PC-Programmierung Integer overflow in C++ mit Exception erfassen


von edelhannes (Gast)


Lesenswert?

Hallo zusammen,

ich möchte Integer-overflows mittels Exceptions behandeln. Um ein 
Beispiel zu geben:
Es sollen zwei Zahlen multipliziert werden, diese beiden Zahlen werden 
mittels cin in zwei Integer-Variablen a und b eingelesen, das Ergebnis 
in die Variable c. Wenn eine Eingabe dazu führt, dass eine Variable 
überläuft soll es mittels Ausnahme erkannt werden und eine Fehlermeldung 
ausgegeben werden.

Wie könnte das als Code aussehen?

von Peter II (Gast)


Lesenswert?

edelhannes schrieb:
> Wie könnte das als Code aussehen?

geht meines Wissens nicht in C++

von edelhannes (Gast)


Lesenswert?

In Ordnung, kann man sonst wie erkennen wann eine Variable überläuft?

Vielleicht irgendwie in Verbindung mit narrow_cast? Ich könnte ja die 
Variablen als double-typen deklarieren und dann eine Konvertierung in 
int mittels narrow_cast vornehmen. Oder bin ich da auf dem Holzweg.

von Peter II (Gast)


Lesenswert?

edelhannes schrieb:
> In Ordnung, kann man sonst wie erkennen wann eine Variable überläuft?

rechnet mit bigint, wenn der Ergebnis > max_int ist dann würde es 
überlaufen.

von Dr. Sommer (Gast)


Lesenswert?

Google zeigt diverse Resultate wie man eine Multiplikation auf Überlauf 
prüft. Es gibt keine direkte/einfache Methode. Nimm eine der zu 
findenden Varianten und füge den Exception-Code hinzu.

narrow_cast gibts im C++ Standard nicht. Nach double konvertieren ist 
immer gefährlich, da kann man ggf. Präzision verlieren.

von Stefan S. (Gast)


Lesenswert?

Muss die Erklärung denn in Deutsch sein? Wenn nicht dann findet man ja 
reichlich Hinweise, denn so ungewöhnlich ist die Frage ja nicht. Etwa

https://stackoverflow.com/questions/199333/how-to-detect-integer-overflow

von edelhannes (Gast)


Lesenswert?

Stefan S. schrieb:
> Muss die Erklärung denn in Deutsch sein?

nein natürlich nicht :-)
Danke für den Link

Peter II schrieb:
> rechnet mit bigint, wenn der Ergebnis > max_int ist dann würde es
> überlaufen.
Das ist ja schon fast zu einfach.

von edelhannes (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Es gibt keine direkte/einfache Methode.

Das ist eigentlich die Info die ich brauche, das wusste ich nicht.

von pjotr_pan (Gast)


Lesenswert?

edelhannes schrieb:
> Das ist eigentlich die Info die ich brauche, das wusste ich nicht.

Die einfachste Lösung wird sein, das du keine Werte eingibst die einen 
Überlauf erzeugen, damit nimmst du dem Computer auch noch Denkarbeit ab, 
das kann der Mensch ohnehin besser.

von Scott Meyers (Gast)


Lesenswert?

Schreib Dir ne eigene Klasse, die das macht.

Das Verhalten der prim. DT ist vorgegeben. Willst Du was anderes ... 
mach es selbst.

von Dr. Sommer (Gast)


Lesenswert?

Scott Meyers schrieb:
> Schreib Dir ne eigene Klasse, die das macht.
Ich glaub darauf wär er schon gekommen. Nur weil man etwas in eine 
Klasse verpackt, kann es nicht plötzlich kniffelige Berechnungen 
durchführen. Die Frage war, wie man Overflows erkennt, was 
portabel/standardkonform nicht offensichtlich ist.

von Cyberpunk (Gast)


Lesenswert?

Ist Inline-Assembler keine zulässige Lösung?

von Scott Meyers (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Scott Meyers schrieb:
>> Schreib Dir ne eigene Klasse, die das macht.
> Ich glaub darauf wär er schon gekommen. Nur weil man etwas in eine
> Klasse verpackt, kann es nicht plötzlich kniffelige Berechnungen
> durchführen.

das war auch nicht die Behauptung. Trotzdem ist es möglich!

> Die Frage war, wie man Overflows erkennt, was
> portabel/standardkonform nicht offensichtlich ist.

von edelhannes (Gast)


Lesenswert?

Cyberpunk schrieb:
> Ist Inline-Assembler keine zulässige Lösung?

Um den Status des overflow-Flags zu sehen? Keine Ahnung wie man das 
macht..

von Peter II (Gast)


Lesenswert?

Cyberpunk schrieb:
> Ist Inline-Assembler keine zulässige Lösung?

wenn es Plattform unabhängig sein soll. NEIN

von Dr. Sommer (Gast)


Lesenswert?

edelhannes schrieb:
> Um den Status des overflow-Flags zu sehen? Keine Ahnung wie man das
> macht..

Also z.B. beim ARMv7M wird das Carry Flag überhaupt nicht bei der 
Multiplikation gesetzt. Das bringts also nicht so wirklich...

von Rolf M. (rmagnus)


Lesenswert?

edelhannes schrieb:
> Cyberpunk schrieb:
>> Ist Inline-Assembler keine zulässige Lösung?
>
> Um den Status des overflow-Flags zu sehen? Keine Ahnung wie man das
> macht..

Je nach Architektur gibt's in Assembler ggf. gar keinen Overflow bei 
Multiplikationen, weil das Ergebnis nicht auf die gleiche Größe 
gezwungen wird, wie die Operanden. So ist es beispielsweise bei x86 und 
beim AVR.

von Daniel A. (daniel-a)


Angehängte Dateien:

Lesenswert?

Ich habe schnell eine Klasse dafür erstellt, ist im Anhang zu finden. Es 
können sich durchaus noch kleinere Fehler darin befinden, und es findet 
damit keine Integer Promotion statt, scheint aber mehr oder weniger zu 
funktionieren.

von Peter II (Gast)


Lesenswert?

Daniel A. schrieb:
1
  T r = x * y;
2
  if( r / x != y )

hoffentlich wird nie mit 0 multipliziert.

von Dr. Sommer (Gast)


Lesenswert?

Daniel A. schrieb:
> Es
> können sich durchaus noch kleinere Fehler darin befinden
Leider ja:
1. Der Overflow von signed Zahlen ist undefiniertes Verhalten, somit 
kann z.B. der if-Block im + Operator wegoptimiert werden und die 
Exception wird ggf. nie ausgelöst. Das lässt sich reparieren, indem man 
vor der Operation den Bereich prüft. 
std::numeric_limits<T>::max()/min() hilft dabei.

2. Statt der C-Casts (T)... würde ich lieber static_cast<T> (...) 
nutzen.

3. Ich würde mit static_assert sicherstellen ob T/U überhaupt Zahlen 
sind.

4.
1
template<typename U>
2
OverflowCheckingNumber( U y ){
3
  if( y != (U)(T)y )
Das greift leider nicht (immer). Wenn man z.B. Signed->unsigned->signed 
castet, kann sehr wohl das gleiche rauskommen, obwohl die Zahl nicht als 
"unsigned" darstellbar ist. Hier braucht man Overloads um alle 
Spezialfälle abzudecken...

5.
1
template<typename U> operator U() const;
Das halte ich für ziemlich gefährlich - ein Typ der in alles umwandelbar 
ist! Da würde ich lieber eine Funktion für nehmen.

6. Man könnte noch großzügig "constexpr" verteilen.

7. Ich würde noch Vergleichsoperatoren sowie Copy/Move-Konstruktoren 
einbauen.

von Rolf M. (rmagnus)


Lesenswert?

Dr. Sommer schrieb:
> 5.template<typename U> operator U() const;Das halte ich für ziemlich
> gefährlich - ein Typ der in alles umwandelbar
> ist!

Nö, nur in das, wohin auch T implizit konvertiert werden kann.

von Dr. Sommer (Gast)


Lesenswert?

Rolf M. schrieb:
> Nö, nur in das, wohin auch T implizit konvertiert werden kann.

Achja, okay weil bei der Rückgabe kein cast ist. Man könnte es noch 
etwas aufhübschen:
1
#include <type_traits>
2
#include <utility>
3
4
template<typename U, class X = typename std::enable_if<std::is_convertible<T, U>::value>::type>
5
operator U() const { ...
So gibts etwas nettere Fehlermeldungen und man könnte es überladen falls 
nötig.

Beitrag #5157268 wurde vom Autor gelöscht.
von Daniel A. (daniel-a)


Angehängte Dateien:

Lesenswert?

Hier nochmal eine neue Version, mit ein paar Bugfixes. Sorry wegen dem 
letzten von mir gelöschten Beitrag, mir ist im letzten Moment noch ein 
Fehler aufgefallen.

von edelhannes (Gast)


Lesenswert?

Daniel A. schrieb:
> Hier nochmal eine neue Version

Wow ich bin eigentlich noch nicht so fortgeschritten, dass ich im ganzen 
verstehe was da gemacht wird. Danke trotzdem für deine Mühe, ich werde 
wohl etwas simpleres ausprobieren müssen. Ich habe erst die Grundlagen 
von C++ durch, d.h. alles bis simple Klassen.

von Jochen (Gast)


Lesenswert?

Mal einfach ausgedrückt: Diese Überlauf-Erkennungs-Operationen "sehen" 
für den Compiler teilweise sinnlos aus und sie werden mitunter 
wegoptimiert. Da gibt es endlose Feinheiten zu beachten. Ganz viele 
Sicherheitslücken in Software basieren exakt darauf, dass jemand 
Überläufe nicht oder nicht korrekt abfängt. Da könnte man ganze Bücher 
drüber schreiben.

In Bereichen, wo Softwarefehler Menschen verletzen oder gar töten 
könnten (Flugzeug, ...) werden deshalb gerne Sprachen verwendet, die 
Überlauf von Haus aus erkennen und behandeln. C kommt natürlich auch 
vor, aber der Output vom Compiler wird intensiv getestet.

Siehe auch hier für einen kleinen Einstieg:

http://www.fefe.de/intof.html

von Peter II (Gast)


Lesenswert?

Jochen schrieb:
> Ganz viele
> Sicherheitslücken in Software basieren exakt darauf, dass jemand
> Überläufe nicht oder nicht korrekt abfängt.

dabei geht es aber um Speicherüberläufe, das hat nur indirekt etwas 
damit zu tun.

Beitrag #5158343 wurde von einem Moderator gelöscht.
von Jochen (Gast)


Lesenswert?

Peter II schrieb:
> dabei geht es aber um Speicherüberläufe, das hat nur indirekt etwas
> damit zu tun.

Das eine hat nicht immer, aber oft direkt mit dem anderen zu tun. Im 
Link oben ist ein schönes Beispiel aus einer älteren Version von 
libiberty:
1
if (*p == '*')
2
            {
3
              ++p;
4
              total_width += abs (va_arg (ap, int));
5
            }

total_width könnte überlaufen, da keine Prüfung implementiert ist. Nach 
Addition eines positiven Wertes wird total_width also kleiner. Als folge 
wird zu wenig Speicher reserviert -> Speicherüberlauf.

Außerdem kann abs(...) auch negativ werden, mit gleicher Folge wie oben. 
Dazu braucht man nur INT_MIN als Argument übergeben, was im obigen 
Beispiel durch Benutzereingabe möglich ist.

Beitrag #5158677 wurde von einem Moderator gelöscht.
Beitrag #5158736 wurde von einem Moderator gelöscht.
Beitrag #5159283 wurde von einem Moderator gelöscht.
Beitrag #5159536 wurde von einem Moderator gelöscht.
Beitrag #5160088 wurde von einem Moderator gelöscht.
Beitrag #5160644 wurde von einem Moderator gelöscht.
Beitrag #5161267 wurde von einem Moderator gelöscht.
Beitrag #5161590 wurde von einem Moderator gelöscht.
Beitrag #5162002 wurde von einem Moderator gelöscht.
Beitrag #5162547 wurde von einem Moderator gelöscht.
Beitrag #5162639 wurde von einem Moderator gelöscht.
Beitrag #5165579 wurde von einem Moderator gelöscht.
Beitrag #5165591 wurde von einem Moderator gelöscht.
Beitrag #5165594 wurde von einem Moderator gelöscht.
Beitrag #5165596 wurde von einem Moderator gelöscht.
Beitrag #5165702 wurde von einem Moderator gelöscht.
von Bert3 (Gast)


Lesenswert?

Such mal nach safeint bei codeplex ist von microsoft

Beitrag #5165823 wurde von einem Moderator gelöscht.
Beitrag #5166146 wurde von einem Moderator gelöscht.
Beitrag #5166161 wurde von einem Moderator gelöscht.
von Nase (Gast)


Lesenswert?

Jochen schrieb:
> Diese Überlauf-Erkennungs-Operationen "sehen"
> für den Compiler teilweise sinnlos aus und sie werden mitunter
> wegoptimiert.
Das ist aber dann ein Fehler im Compiler.
Der Compiler darf sie natürlich wegoptimieren, wenn sie tatsächlich 
sinnlos sind, denn dann tritt ja auch kein Überlauf auf. Aber das muss 
er auch garantieren.

Es gab ähnliche Diskussionen, als GCC angefangen hat, scharf zu 
optimieren und die Tests gegen Pufferüberläufe wegzuoptimieren. Das 
haben die ganz schnell wieder sein gelassen...


Daniel A. schrieb:
> Hier nochmal eine neue Version, mit ein paar Bugfixes. Sorry wegen dem
> letzten von mir gelöschten Beitrag, mir ist im letzten Moment noch ein
> Fehler aufgefallen.
Deine Klasse krankt an genau dem o.g. Problem: Du führst einfach die 
Berechnung aus und guckst hinterher, ob das Ergebnis korrekt ist, indem 
du zurückrechnest.
Ein Überlauf bei signed int ist aber nicht nur unschön, sondern auch 
undefined behaviour! D.h., der Compiler dürfte das alles wegoptimieren 
und durch exit(0) ersetzen...

Mehr dazu:
https://www.securecoding.cert.org/confluence/display/c/INT31-C.+Ensure+that+integer+conversions+do+not+result+in+lost+or+misinterpreted+data

von Nase (Gast)


Lesenswert?


Beitrag #5167762 wurde von einem Moderator gelöscht.
Beitrag #5167781 wurde von einem Moderator gelöscht.
Beitrag #5167790 wurde von einem Moderator gelöscht.
Beitrag #5167794 wurde von einem Moderator gelöscht.
Beitrag #5167801 wurde von einem Moderator gelöscht.
Beitrag #5167803 wurde von einem Moderator gelöscht.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.