[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>&nbsp;</DIV>
<DIV><FONT face=3DVerdana size=3D2>Code before:</FONT></DIV>
<DIV><FONT size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT size=3D2><FONT face=3D"Courier New">&nbsp;&nbsp;public string =
GetString=20
(int len, bool wide)<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;if (wide)=20
{<BR>&nbsp;&nbsp;&nbsp;&nbsp;char[] chars =3D new=20
char[len];<BR>&nbsp;&nbsp;&nbsp;&nbsp;for (int i =3D 0; i &lt; len; ++i) =

{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int lo =3D ((byte) GetByte ()) &amp;=20
0xFF;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int hi =3D ((byte) GetByte ()) =
&amp;=20
0xFF;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chars[i] =3D (char) (lo | ( hi =
&lt;&lt;=20
8));<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;return new =
String=20
(chars);<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;else=20
{<BR>&nbsp;&nbsp;&nbsp;&nbsp;byte[] result =3D new byte[len +=20
1];<BR>&nbsp;&nbsp;&nbsp;&nbsp;Array.Copy (GetBytes (len, false), =
result,=20
len);<BR>&nbsp;&nbsp;&nbsp;&nbsp;return (encoder.GetString=20
(result));<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;}<BR></FONT>&nbsp;</FONT=
></DIV>
<DIV><FONT face=3DVerdana size=3D2>Fix:</FONT></DIV>
<DIV><FONT size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT size=3D2><FONT face=3D"Courier New">&nbsp;&nbsp;public string =
GetString=20
(int len, bool wide)<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;if (wide)=20
{<BR>&nbsp;&nbsp;&nbsp;&nbsp;char[] chars =3D new=20
char[len];<BR>&nbsp;&nbsp;&nbsp;&nbsp;for (int i =3D 0; i &lt; len; ++i) =

{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int lo =3D ((byte) GetByte ()) &amp;=20
0xFF;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int hi =3D ((byte) GetByte ()) =
&amp;=20
0xFF;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chars[i] =3D (char) (lo | ( hi =
&lt;&lt;=20
8));<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;return new =
String=20
(chars);<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;else=20
{<BR>&nbsp;&nbsp;&nbsp;&nbsp;byte[] result =3D <FONT color=3D#ff0000>new =

byte[len]</FONT>;<BR>&nbsp;&nbsp;&nbsp;&nbsp;Array.Copy (GetBytes (len, =
false),=20
result, len);<BR>&nbsp;&nbsp;&nbsp;&nbsp;return (encoder.GetString=20
(result));<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;}<BR></FONT>&nbsp;</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>&nbsp;</DIV>
<DIV><FONT face=3DVerdana size=3D2>Code before:</FONT></DIV>
<DIV><FONT size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3D"Courier New" size=3D2>&nbsp;&nbsp;private object =
GetDecimalValue=20
(byte precision, byte scale)<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;int[] =
bits =3D=20
new int[4] {0,0,0,0};</FONT></DIV>
<DIV><FONT face=3D"Courier New"></FONT>&nbsp;</DIV>
<DIV><FONT face=3D"Courier New" size=3D2>&nbsp;&nbsp;&nbsp;int len =3D =
(comm.GetByte()=20
&amp; 0xff) - 1;<BR>&nbsp;&nbsp;&nbsp;bool positive =3D (comm.GetByte () =
=3D=3D=20
1);</FONT></DIV>
<DIV><FONT face=3D"Courier New"></FONT>&nbsp;</DIV>
<DIV><FONT face=3D"Courier New" size=3D2>&nbsp;&nbsp;&nbsp;if (len &lt;=20
0)<BR>&nbsp;&nbsp;&nbsp;&nbsp;return null;<BR>&nbsp;&nbsp;&nbsp;if (len =
&gt;=20
16)<BR>&nbsp;&nbsp;&nbsp;&nbsp;throw new OverflowException =
();</FONT></DIV>
<DIV><FONT face=3D"Courier New"></FONT>&nbsp;</DIV>
<DIV><FONT face=3D"Courier New" size=3D2>&nbsp;&nbsp;&nbsp;for (int i =
=3D 0, index =3D=20
0; i &lt; len &amp;&amp; i &lt; 16; i +=3D 4, index +=3D 1)=20
<BR>&nbsp;&nbsp;&nbsp;&nbsp;bits[index] =3D comm.GetTdsInt =
();</FONT></DIV>
<DIV><FONT face=3D"Courier New"></FONT>&nbsp;</DIV>
<DIV><FONT size=3D2><FONT face=3D"Courier New">&nbsp;&nbsp;&nbsp;if =
(bits [3] !=3D 0)=20
<BR>&nbsp;&nbsp;&nbsp;&nbsp;return new TdsBigDecimal (precision, scale,=20
!positive, =
bits);<BR>&nbsp;&nbsp;&nbsp;else<BR>&nbsp;&nbsp;&nbsp;&nbsp;return=20
new Decimal (bits[0], bits[1], bits[2], !positive,=20
scale);<BR>&nbsp;&nbsp;}<BR></FONT>&nbsp;</FONT></DIV>
<DIV><FONT face=3DVerdana size=3D2>Fix:</FONT></DIV>
<DIV><FONT size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3D"Courier New" size=3D2>&nbsp;&nbsp;private object =
GetDecimalValue=20
(byte precision, byte scale)<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;int[] =
bits =3D=20
new int[4] {0,0,0,0};</FONT></DIV>
<DIV><FONT face=3D"Courier New"></FONT>&nbsp;</DIV>
<DIV><FONT face=3D"Courier New" size=3D2>&nbsp;&nbsp;&nbsp;int len =3D =
(comm.GetByte()=20
&amp; 0xff) - 1;<BR><FONT color=3D#ff0000>&nbsp;&nbsp;&nbsp;if (len &lt; =
0) return=20
null;</FONT></FONT></DIV>
<DIV><FONT face=3D"Courier New" size=3D2><BR>&nbsp;&nbsp;&nbsp;bool =
positive =3D=20
(comm.GetByte () =3D=3D 1);</FONT></DIV>
<DIV><FONT face=3D"Courier New"></FONT>&nbsp;</DIV>
<DIV><FONT face=3D"Courier New" size=3D2>&nbsp;&nbsp;&nbsp;if (len &gt;=20
16)<BR>&nbsp;&nbsp;&nbsp;&nbsp;throw new OverflowException =
();</FONT></DIV>
<DIV><FONT face=3D"Courier New"></FONT>&nbsp;</DIV>
<DIV><FONT face=3D"Courier New" size=3D2>&nbsp;&nbsp;&nbsp;for (int i =
=3D 0, index =3D=20
0; i &lt; len &amp;&amp; i &lt; 16; i +=3D 4, index +=3D 1)=20
<BR>&nbsp;&nbsp;&nbsp;&nbsp;bits[index] =3D comm.GetTdsInt =
();</FONT></DIV>
<DIV><FONT face=3D"Courier New"></FONT>&nbsp;</DIV>
<DIV><FONT size=3D2><FONT face=3D"Courier New">&nbsp;&nbsp;&nbsp;if =
(bits [3] !=3D 0)=20
<BR>&nbsp;&nbsp;&nbsp;&nbsp;return new TdsBigDecimal (precision, scale,=20
!positive, =
bits);<BR>&nbsp;&nbsp;&nbsp;else<BR>&nbsp;&nbsp;&nbsp;&nbsp;return=20
new Decimal (bits[0], bits[1], bits[2], !positive,=20
scale);<BR>&nbsp;&nbsp;}<BR></FONT>&nbsp;</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>&nbsp;</DIV></BODY></HTML>

------=_NextPart_000_0508_01C30842.16822EC0--