>Submitter-Id: net >Originator: Marek Baczynski >Organization: >Confidential: no >Synopsis: const * loses highest order byte. >Severity: serious >Priority: medium >Category: c++ >Class: wrong-code >Release: 3.3.2 (Debian) (Debian testing/unstable) >Environment: System: Linux imbaczek 2.4.24-1-686 #1 Tue Jan 6 21:29:44 EST 2004 i686 GNU/Linux Architecture: i686
host: i486-pc-linux-gnu build: i486-pc-linux-gnu target: i486-pc-linux-gnu configured with: ../src/configure -v --enable-languages=c,c++,java,f77,pascal,objc,ada,treelang --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-gxx-include-dir=/usr/include/c++/3.3 --enable-shared --with-system-zlib --enable-nls --without-included-gettext --enable-__cxa_atexit --enable-clocale=gnu --enable-debug --enable-java-gc=boehm --enable-java-awt=xlib --enable-objc-gc i486-linux >Description: Breakpoint 1, operator*(Liczba const&, Liczba const&) ([EMAIL PROTECTED], [EMAIL PROTECTED]) at duze.cc:183 183 for (i = l2->start; i<LEN; ++i) { (gdb) p l1 $1 = (const Liczba *) 0xbffff8f0 (gdb) p l2 $2 = (const Liczba *) 0xbffff960 (gdb) watch l1 Hardware watchpoint 2: l1 (gdb) continue Continuing. Hardware watchpoint 2: l1 Old value = (const Liczba *) 0xbffff8f0 New value = (const Liczba *) 0xfff8f0 operator*(Liczba const&, Liczba const&) ([EMAIL PROTECTED], [EMAIL PROTECTED]) at duze.cc:184 184 for (j = LEN-1; j>=l1->start; --j) { (gdb) continue Continuing. Program received signal SIGSEGV, Segmentation fault. 0x08048f0e in operator*(Liczba const&, Liczba const&) ([EMAIL PROTECTED], [EMAIL PROTECTED]) at duze.cc:184 184 for (j = LEN-1; j>=l1->start; --j) { (gdb) >How-To-Repeat: Complete source: // bignums.cc #include <iostream> #include <cstring> using namespace std; #define LEN 100 #define BASE 10 class Liczba { signed char liczba[LEN]; int len; int start; inline void from_string(const char *); public: Liczba(const char * s) { this->from_string(s); } Liczba(int i) { char s[LEN]; snprintf(s, LEN, "%d", i); this->from_string(s); } Liczba(const Liczba& l) { int i; for (i = 0; i<LEN; ++i) this->liczba[i] = l.liczba[i]; this->len = l.len; this->start = l.start; } friend ostream& operator<<(ostream&, const Liczba&); friend istream& operator>>(istream&, Liczba&); friend bool operator<(const Liczba&, const Liczba&); friend bool operator==(const Liczba&, const Liczba&); friend Liczba& operator<<=(Liczba&, int); friend Liczba& operator+=(Liczba&, const Liczba&); friend Liczba& operator-=(Liczba&, const Liczba&); friend Liczba& operator*=(Liczba&, const Liczba&); friend Liczba& operator/=(Liczba&, const Liczba&); friend Liczba operator+(const Liczba&, const Liczba&); friend Liczba operator-(const Liczba&, const Liczba&); friend Liczba operator*(const Liczba&, const Liczba&); }; void Liczba::from_string(const char *s) { int i; len = strlen(s); start = LEN-len; for (i = 0; i<start; ++i) liczba[i] = 0; for (i = start; i<LEN; ++i) liczba[i] = s[i-start]-'0'; } ostream& operator<<(ostream& o, const Liczba& l) { char s[LEN+1]; int i; for (i=l.start; i<LEN; ++i) s[i-l.start] = l.liczba[i]+'0'; s[i-l.start] = 0; o << s; return o; } istream& operator>>(istream& is, Liczba& l) { char s[LEN+1]; is >> s; l.from_string(s); return is; } // -------------------------------------------------------------------------- // porownania bool operator<(const Liczba& a, const Liczba& b) { int i; if (a.start > b.start) return true; else if (a.start < b.start) return false; i = a.start; while (a.liczba[i] == b.liczba[i]) ++i; if (a.liczba[i] < b.liczba[i]) return true; else return false; } // -------------------------------------------------------------------------- // przesuniecia Liczba& operator<<=(Liczba& a, int s) { int i; memmove(a.liczba+a.start-s, a.liczba+a.start, LEN-a.start); for (i = LEN-s; i < LEN; ++i) a.liczba[i] = 0; a.start -= s; return a; } // -------------------------------------------------------------------------- // dodawanie Liczba& operator+=(Liczba& a, const Liczba& b) { int i, c=0; for (i = LEN-1; i>=b.start; --i) { a.liczba[i] += b.liczba[i]; c = a.liczba[i]/BASE; a.liczba[i] %= BASE; a.liczba[i-1] += c; } if (b.start <= a.start) { a.start = b.start - c; a.len = b.len + c; } return a; } Liczba operator+(const Liczba& a, const Liczba& b) { Liczba r(a); r += b; return r; } // ------------------------------------------------------------------------- // odejmowanie Liczba& operator-=(Liczba& a, const Liczba& b) { int i, c=0; for (i = LEN-1; i>=b.start; --i) { a.liczba[i] -= b.liczba[i]; cout << (int)a.liczba[i] << ' '; c = -(a.liczba[i]<0); a.liczba[i] = (a.liczba[i]+BASE)%BASE; cout << c << ' ' << (int)a.liczba[i] << ' '; a.liczba[i-1] += c; cout << (int)a.liczba[i-1] << endl; } if (a.liczba[a.start] == 0) { ++a.start; --a.len; } return a; } Liczba operator-(const Liczba& a, const Liczba& b) { Liczba r(a); r -= b; return r; } // -------------------------------------------------------------------------- // mnozenie Liczba operator*(const Liczba& a, const Liczba& b) { Liczba tmp(0), r(0); const Liczba *l1=NULL, *l2=NULL; int i, j, tmp1; if (a<b) { l1 = &b; l2 = &a; } else { l1 = &a; l2 = &b; } //l2 = (const Liczba*)(0xbf000000|(int)l2); //l1 = (const Liczba*)(0xbf000000|(int)l1); for (i = l2->start; i<LEN; ++i) { for (j = LEN-1; j>=l1->start; --j) { tmp1 = tmp.liczba[j-i] + l1->liczba[j] * l2->liczba[LEN-i-1]; tmp.liczba[j-i] = tmp1%10; tmp.liczba[j-i-1] = tmp1/10; } r += tmp; tmp = Liczba(0); } return r; } // -------------------------------------------------------------------------- void test() { char ch; Liczba a(0), b(0); // bug here, left as is while (cin) { cin >> ch >> a >> b; cout << a << ch << b << " = "; switch (ch) { case '+': cout << (a+b); break; case '-': cout << (a-b); break; case '<': cout << (a<b); break; case '*': cout << (a*b); break; default: break; } cout << endl; } } int main() { test(); return 0; } // EOF A test suite: + 9 1 + 99 11 + 20 1000000000000 + 900000000000 100000000000 - 10 9 - 9 5 - 5 9 - 99999 88888 - 88888 9999 < 5 9 < 100 101 < 99999 99998 * 10 251 Compile and run: $ g++ bignums.cc -Wall -g -o bignums $ ./bignums <testsuite Tested with gcc-3.2 and gcc-3.3, segfaults on both. Didn't test in C. >Fix: Compile with any -O. Didn't test assigment to temporary variables.