[Mono-list] 2 bugs in Mono.Data.Tds.Protocol namespace
Igor Nosyryev
nosyryev@attbi.com
Mon, 21 Apr 2003 20:10:43 -0400
This is a multi-part message in MIME format.
------=_NextPart_000_0508_01C30842.16822EC0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
1. Class TdsComm. Method GetString adds extra byte to a string at end. =
It suppose to be '\0', but '\0' is valid value in .NET string, so this =
byte must not be used.=20
Code before:
public string GetString (int len, bool wide)
{
if (wide) {
char[] chars =3D new char[len];
for (int i =3D 0; i < len; ++i) {
int lo =3D ((byte) GetByte ()) & 0xFF;
int hi =3D ((byte) GetByte ()) & 0xFF;
chars[i] =3D (char) (lo | ( hi << 8));
}
return new String (chars);
}
else {
byte[] result =3D new byte[len + 1];
Array.Copy (GetBytes (len, false), result, len);
return (encoder.GetString (result));
}
}
=20
Fix:
public string GetString (int len, bool wide)
{
if (wide) {
char[] chars =3D new char[len];
for (int i =3D 0; i < len; ++i) {
int lo =3D ((byte) GetByte ()) & 0xFF;
int hi =3D ((byte) GetByte ()) & 0xFF;
chars[i] =3D (char) (lo | ( hi << 8));
}
return new String (chars);
}
else {
byte[] result =3D new byte[len];
Array.Copy (GetBytes (len, false), result, len);
return (encoder.GetString (result));
}
}
=20
2. Class Tds. Method GetDecimalValue. Method reads extra byte if a =
DECIMAL field contains NULL. As a result server's response is parsed =
incorrectly and this method fires an exception.
Code before:
private object GetDecimalValue (byte precision, byte scale)
{
int[] bits =3D new int[4] {0,0,0,0};
int len =3D (comm.GetByte() & 0xff) - 1;
bool positive =3D (comm.GetByte () =3D=3D 1);
if (len < 0)
return null;
if (len > 16)
throw new OverflowException ();
for (int i =3D 0, index =3D 0; i < len && i < 16; i +=3D 4, index =
+=3D 1)=20
bits[index] =3D comm.GetTdsInt ();
if (bits [3] !=3D 0)=20
return new TdsBigDecimal (precision, scale, !positive, bits);
else
return new Decimal (bits[0], bits[1], bits[2], !positive, scale);
}
=20
Fix:
private object GetDecimalValue (byte precision, byte scale)
{
int[] bits =3D new int[4] {0,0,0,0};
int len =3D (comm.GetByte() & 0xff) - 1;
if (len < 0) return null;
bool positive =3D (comm.GetByte () =3D=3D 1);
if (len > 16)
throw new OverflowException ();
for (int i =3D 0, index =3D 0; i < len && i < 16; i +=3D 4, index =
+=3D 1)=20
bits[index] =3D comm.GetTdsInt ();
if (bits [3] !=3D 0)=20
return new TdsBigDecimal (precision, scale, !positive, bits);
else
return new Decimal (bits[0], bits[1], bits[2], !positive, scale);
}
=20
----------------------------------------
Igor Nosyryev
E-mail: nosyryev@attbi.com
------=_NextPart_000_0508_01C30842.16822EC0
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Diso-8859-1">
<META content=3D"MSHTML 6.00.2800.1141" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV><FONT face=3DVerdana size=3D2>1. Class TdsComm. Method GetString =
adds extra=20
byte to a string at end. It suppose to be '\0', but '\0' is valid value =
in .NET=20
string, so this byte must not be used. </FONT></DIV>
<DIV><FONT face=3DVerdana size=3D2></FONT> </DIV>
<DIV><FONT face=3DVerdana size=3D2>Code before:</FONT></DIV>
<DIV><FONT size=3D2></FONT> </DIV>
<DIV><FONT size=3D2><FONT face=3D"Courier New"> public string =
GetString=20
(int len, bool wide)<BR> {<BR> if (wide)=20
{<BR> char[] chars =3D new=20
char[len];<BR> for (int i =3D 0; i < len; ++i) =
{<BR> int lo =3D ((byte) GetByte ()) &=20
0xFF;<BR> int hi =3D ((byte) GetByte ()) =
&=20
0xFF;<BR> chars[i] =3D (char) (lo | ( hi =
<<=20
8));<BR> }<BR> return new =
String=20
(chars);<BR> }<BR> else=20
{<BR> byte[] result =3D new byte[len +=20
1];<BR> Array.Copy (GetBytes (len, false), =
result,=20
len);<BR> return (encoder.GetString=20
(result));<BR> }<BR> }<BR></FONT> </FONT=
></DIV>
<DIV><FONT face=3DVerdana size=3D2>Fix:</FONT></DIV>
<DIV><FONT size=3D2></FONT> </DIV>
<DIV><FONT size=3D2><FONT face=3D"Courier New"> public string =
GetString=20
(int len, bool wide)<BR> {<BR> if (wide)=20
{<BR> char[] chars =3D new=20
char[len];<BR> for (int i =3D 0; i < len; ++i) =
{<BR> int lo =3D ((byte) GetByte ()) &=20
0xFF;<BR> int hi =3D ((byte) GetByte ()) =
&=20
0xFF;<BR> chars[i] =3D (char) (lo | ( hi =
<<=20
8));<BR> }<BR> return new =
String=20
(chars);<BR> }<BR> else=20
{<BR> byte[] result =3D <FONT color=3D#ff0000>new =
byte[len]</FONT>;<BR> Array.Copy (GetBytes (len, =
false),=20
result, len);<BR> return (encoder.GetString=20
(result));<BR> }<BR> }<BR></FONT> </FONT=
></DIV>
<DIV><FONT face=3DVerdana size=3D2>2. Class Tds. Method GetDecimalValue. =
Method=20
reads extra byte if a DECIMAL field contains NULL. As a result server's =
response=20
is parsed incorrectly and this method fires an exception.</FONT></DIV>
<DIV><FONT face=3DVerdana size=3D2></FONT> </DIV>
<DIV><FONT face=3DVerdana size=3D2>Code before:</FONT></DIV>
<DIV><FONT size=3D2></FONT> </DIV>
<DIV><FONT face=3D"Courier New" size=3D2> private object =
GetDecimalValue=20
(byte precision, byte scale)<BR> {<BR> int[] =
bits =3D=20
new int[4] {0,0,0,0};</FONT></DIV>
<DIV><FONT face=3D"Courier New"></FONT> </DIV>
<DIV><FONT face=3D"Courier New" size=3D2> int len =3D =
(comm.GetByte()=20
& 0xff) - 1;<BR> bool positive =3D (comm.GetByte () =
=3D=3D=20
1);</FONT></DIV>
<DIV><FONT face=3D"Courier New"></FONT> </DIV>
<DIV><FONT face=3D"Courier New" size=3D2> if (len <=20
0)<BR> return null;<BR> if (len =
>=20
16)<BR> throw new OverflowException =
();</FONT></DIV>
<DIV><FONT face=3D"Courier New"></FONT> </DIV>
<DIV><FONT face=3D"Courier New" size=3D2> for (int i =
=3D 0, index =3D=20
0; i < len && i < 16; i +=3D 4, index +=3D 1)=20
<BR> bits[index] =3D comm.GetTdsInt =
();</FONT></DIV>
<DIV><FONT face=3D"Courier New"></FONT> </DIV>
<DIV><FONT size=3D2><FONT face=3D"Courier New"> if =
(bits [3] !=3D 0)=20
<BR> return new TdsBigDecimal (precision, scale,=20
!positive, =
bits);<BR> else<BR> return=20
new Decimal (bits[0], bits[1], bits[2], !positive,=20
scale);<BR> }<BR></FONT> </FONT></DIV>
<DIV><FONT face=3DVerdana size=3D2>Fix:</FONT></DIV>
<DIV><FONT size=3D2></FONT> </DIV>
<DIV><FONT face=3D"Courier New" size=3D2> private object =
GetDecimalValue=20
(byte precision, byte scale)<BR> {<BR> int[] =
bits =3D=20
new int[4] {0,0,0,0};</FONT></DIV>
<DIV><FONT face=3D"Courier New"></FONT> </DIV>
<DIV><FONT face=3D"Courier New" size=3D2> int len =3D =
(comm.GetByte()=20
& 0xff) - 1;<BR><FONT color=3D#ff0000> if (len < =
0) return=20
null;</FONT></FONT></DIV>
<DIV><FONT face=3D"Courier New" size=3D2><BR> bool =
positive =3D=20
(comm.GetByte () =3D=3D 1);</FONT></DIV>
<DIV><FONT face=3D"Courier New"></FONT> </DIV>
<DIV><FONT face=3D"Courier New" size=3D2> if (len >=20
16)<BR> throw new OverflowException =
();</FONT></DIV>
<DIV><FONT face=3D"Courier New"></FONT> </DIV>
<DIV><FONT face=3D"Courier New" size=3D2> for (int i =
=3D 0, index =3D=20
0; i < len && i < 16; i +=3D 4, index +=3D 1)=20
<BR> bits[index] =3D comm.GetTdsInt =
();</FONT></DIV>
<DIV><FONT face=3D"Courier New"></FONT> </DIV>
<DIV><FONT size=3D2><FONT face=3D"Courier New"> if =
(bits [3] !=3D 0)=20
<BR> return new TdsBigDecimal (precision, scale,=20
!positive, =
bits);<BR> else<BR> return=20
new Decimal (bits[0], bits[1], bits[2], !positive,=20
scale);<BR> }<BR></FONT> </FONT></DIV>
<DIV><FONT face=3DVerdana=20
size=3D2>----------------------------------------</FONT></DIV>
<DIV><FONT face=3DVerdana size=3D2>Igor Nosyryev</FONT></DIV>
<DIV><FONT size=3D2><FONT face=3DVerdana>E-mail: </FONT><A=20
href=3D"mailto:nosyryev@attbi.com"><FONT=20
face=3DVerdana>nosyryev@attbi.com</FONT></A></FONT></DIV>
<DIV><FONT size=3D2></FONT> </DIV></BODY></HTML>
------=_NextPart_000_0508_01C30842.16822EC0--