[net.bugs.4bsd] Ingres bug in 4.2 BSD

steve@tellab2.UUCP (Steve Harpster) (02/12/85)

Subject: Retrieving long relation returns bad character count
Index:	~ingres/source/libq/IIn_ret.c 4.2BSD

Description:
	Occasionally, a C program (run through equel) which is trying to
	retrieve tuples from an Ingres database returns the message
	"IIn_ret: bad pb_get-1 <# bytes read>".
Repeat-By:
	Create a relation with a character domain of length 255 (the
	maximum). Now have a C program try and retrieve a tuple from it.
Fix:
	Simple type conflicts. Casts fix the problem. The diffs are below:

*** /tmp/old_IIn_ret.c	Tue Feb 12 13:22:31 1985
--- /user2/ingres/source/libq/IIn_ret.c	Tue Feb 12 12:50:28 1985
***************
*** 46,53
          ret = &IIr_sym;
  
  	if (ret->len &= 0377)
! 		if (IIpb_get(&IIpb, temp, ret->len & 0377) != ret->len & 0377)
! 			IIsyserr("IIn_ret: bad pb_get-1 %d", ret->len & 0377);
  
  
  #	ifdef xETR1

--- 46,54 -----
          ret = &IIr_sym;
  
  	if (ret->len &= 0377)
! 		if ((length = IIpb_get(&IIpb, temp, ret->len & 0377)) != (int) (ret->len & 0377))
! 			IIsyserr("IIn_ret: bad pb_get-1, wanted %d got %d",
! 				(int) (ret->len & 0377), length);
  
  
  #	ifdef xETR1

anton@ucbvax.ARPA (Jeff Anton) (02/14/85)

In article <220@tellab2.UUCP> steve@tellab3.UUCP (& Harpster) writes:
>
>Subject: Retrieving long relation returns bad character count
>Index:	~ingres/source/libq/IIn_ret.c 4.2BSD
>
>Description:
>	Occasionally, a C program (run through equel) which is trying to
>	retrieve tuples from an Ingres database returns the message
>	"IIn_ret: bad pb_get-1 <# bytes read>".
>Repeat-By:
>	Create a relation with a character domain of length 255 (the
>	maximum). Now have a C program try and retrieve a tuple from it.
>Fix:
>	Simple type conflicts. Casts fix the problem. The diffs are below:
>
>*** /tmp/old_IIn_ret.c	Tue Feb 12 13:22:31 1985
>--- /user2/ingres/source/libq/IIn_ret.c	Tue Feb 12 12:50:28 1985
>***************
>*** 46,53
>          ret = &IIr_sym;
>  
>  	if (ret->len &= 0377)
>! 		if (IIpb_get(&IIpb, temp, ret->len & 0377) != ret->len & 0377)
>! 			IIsyserr("IIn_ret: bad pb_get-1 %d", ret->len & 0377);
>  
>  
>  #	ifdef xETR1
>
>--- 46,54 -----
>          ret = &IIr_sym;
>  
>  	if (ret->len &= 0377)
>! 		if ((length = IIpb_get(&IIpb, temp, ret->len & 0377)) != (int) (ret->len & 0377))
>! 			IIsyserr("IIn_ret: bad pb_get-1, wanted %d got %d",
>! 				(int) (ret->len & 0377), length);
>  
>  
>  #	ifdef xETR1

The problem with the original code was not typeing but operator precidence.
The '!=' would bind more causeing ret->len to be signextended to int
and the comparison fails; then the result of the compairison is bit wise anded
with 0377.  There are many strange things about this code.  For example,
take the first if statement.  'if (ret->len &= 0377)'  What is this supposed
to do?  ret->len is a char so &= with 0377 is a futile operation.
Below is a much clearer version:
	if (ret->len != 0 &&
	    IIpb_get(&IIpb, temp, ret->len & I1MASK) != (ret->len & I1MASK))
		IIsyserr("IIn_ret: bad pb_get-1, %d", ret->len & I1MASK);

I1MASK is defined in h/ingres.h

nontrivial question: Would casting ret->len as unsigned work better,
not work, look better, or look worse?  I know the answer.

-- 
_________________________
C knows no bounds.
					Jeff Anton
					U.C.Berkeley
					ucbvax!anton
					anton@berkeley.ARPA