const * loses highest order byte.
>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&) (a=@0xbffff960,
b=@0xbffff8f0) 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&) (a=@0xbffff960, b=@0xbffff8f0)
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&) (a=@0xbffff960,
b=@0xbffff8f0) 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.
Reply to: