1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-15 04:09:01 +00:00

Added or enhanced support for the following data types:

SQLTEXT       = 0x23 - text
GUIDTYPE      = 0x24 - uniqueidentifier
NTEXTTYPE     = 0x63 - unicode text (ntext)
BITNTYPE      = 0x68 - boolean
DECIMALNTYPE  = 0x6A - decimal
NUMERICNTYPE  = 0x6C - numeric
FLTNTYPE      = 0x6D - float/real/double
MONEYNTYPE    = 0x6E - money / smallmoeny
BIGBINARYTYPE = 0xAD - binary
BIGCHARTYPE   = 0xAF - char
SQLNCHAR      = 0xEF - unicode char (nchar)

Added detection and handling of null values when processing query responses from the server.
Added DoneProc response token support
Reordered ColumnData and ColumnInfo parsers by data type code to make updates easier.
This commit is contained in:
tomsellers
2012-08-24 10:32:44 +00:00
parent fd32aec639
commit 5ba2007d69
2 changed files with 469 additions and 91 deletions

View File

@@ -1,5 +1,9 @@
# Nmap Changelog ($Id$); -*-text-*- # Nmap Changelog ($Id$); -*-text-*-
o [NSE] Updated mssql.lua library to support additional data types, enchanced
some of the existing data types, added the DoneProc response token, and
reordered code for maintainability. [Tom Sellers]
o [NSE] Added http-slowloris-check script which checks if the server is vulnerable o [NSE] Added http-slowloris-check script which checks if the server is vulnerable
to a Slowloris DoS attack in a safe way. [Aleksandar Nikolic] to a Slowloris DoS attack in a safe way. [Aleksandar Nikolic]

View File

@@ -130,6 +130,11 @@ _ENV = stdnse.module("mssql", stdnse.seeall)
-- * added support for integrated NTLMv1 authentication -- * added support for integrated NTLMv1 authentication
-- --
-- (Patrik Karlsson, Chris Woodbury) -- (Patrik Karlsson, Chris Woodbury)
-- Revised 08/19/2012 - v0.6 - added multiple data types
-- * added detection and handling of null values when processing query responses from the server
-- * added DoneProc response token support
--
-- (Tom Sellers)
local HAVE_SSL, openssl = pcall(require, "openssl") local HAVE_SSL, openssl = pcall(require, "openssl")
@@ -674,30 +679,42 @@ PacketType =
-- TDS response token types -- TDS response token types
TokenType = TokenType =
{ {
ReturnStatus = 0x79, ReturnStatus = 0x79,
TDS7Results = 0x81, TDS7Results = 0x81,
ErrorMessage = 0xAA, ErrorMessage = 0xAA,
InformationMessage = 0xAB, InformationMessage = 0xAB,
LoginAcknowledgement = 0xAD, LoginAcknowledgement = 0xAD,
Row = 0xD1, Row = 0xD1,
OrderBy = 0xA9, OrderBy = 0xA9,
EnvironmentChange = 0xE3, EnvironmentChange = 0xE3,
NTLMSSP_CHALLENGE = 0xed, NTLMSSP_CHALLENGE = 0xed,
Done = 0xFD, Done = 0xFD,
DoneInProc = 0xFF, DoneProc = 0xFE,
DoneInProc = 0xFF,
} }
-- SQL Server/Sybase data types -- SQL Server/Sybase data types
DataTypes = DataTypes =
{ {
SYBINTN = 0x26, SQLTEXT = 0x23,
SYBINT2 = 0x34, GUIDTYPE = 0x24,
SYBINT4 = 0x38, SYBINTN = 0x26,
SYBDATETIME = 0x3D, SYBINT2 = 0x34,
SYBDATETIMN = 0x6F, SYBINT4 = 0x38,
SYBDATETIME = 0x3D,
NTEXTTYPE = 0x63,
BITNTYPE = 0x68,
DECIMALNTYPE = 0x6A,
NUMERICNTYPE = 0x6C,
FLTNTYPE = 0x6D,
MONEYNTYPE = 0x6E,
SYBDATETIMN = 0x6F,
XSYBVARBINARY = 0xA5, XSYBVARBINARY = 0xA5,
XSYBVARCHAR = 0xA7, XSYBVARCHAR = 0xA7,
XSYBNVARCHAR = 0xE7, BIGBINARYTYPE = 0xAD,
BIGCHARTYPE = 0xAF,
XSYBNVARCHAR = 0xE7,
SQLNCHAR = 0xEF,
} }
-- SQL Server login error codes -- SQL Server login error codes
@@ -728,22 +745,27 @@ ColumnInfo =
Parse = Parse =
{ {
[DataTypes.XSYBNVARCHAR] = function( data, pos )
[DataTypes.SQLTEXT] = function( data, pos )
local colinfo = {} local colinfo = {}
local tmp local tmp
pos, colinfo.lts, colinfo.codepage, colinfo.flags, colinfo.charset, pos, colinfo.unknown, colinfo.codepage, colinfo.flags, colinfo.charset = bin.unpack("<ISSC", data, pos )
colinfo.msglen = bin.unpack("<SSSCC", data, pos )
pos, colinfo.tablenamelen = bin.unpack("s", data, pos )
pos, colinfo.tablename = bin.unpack("A" .. (colinfo.tablenamelen * 2), data, pos)
pos, colinfo.msglen = bin.unpack("<C", data, pos )
pos, tmp = bin.unpack("A" .. (colinfo.msglen * 2), data, pos) pos, tmp = bin.unpack("A" .. (colinfo.msglen * 2), data, pos)
colinfo.text = Util.FromWideChar(tmp) colinfo.text = Util.FromWideChar(tmp)
return pos, colinfo return pos, colinfo
end, end,
[DataTypes.SYBINT2] = function( data, pos ) [DataTypes.GUIDTYPE] = function( data, pos )
return ColumnInfo.Parse[DataTypes.SYBDATETIME](data, pos) return ColumnInfo.Parse[DataTypes.SYBINTN](data, pos)
end, end,
[DataTypes.SYBINTN] = function( data, pos ) [DataTypes.SYBINTN] = function( data, pos )
local colinfo = {} local colinfo = {}
local tmp local tmp
@@ -751,25 +773,18 @@ ColumnInfo =
pos, colinfo.unknown, colinfo.msglen = bin.unpack("<CC", data, pos) pos, colinfo.unknown, colinfo.msglen = bin.unpack("<CC", data, pos)
pos, tmp = bin.unpack("A" .. (colinfo.msglen * 2), data, pos ) pos, tmp = bin.unpack("A" .. (colinfo.msglen * 2), data, pos )
colinfo.text = Util.FromWideChar(tmp) colinfo.text = Util.FromWideChar(tmp)
return pos, colinfo return pos, colinfo
end, end,
[DataTypes.SYBINT2] = function( data, pos )
return ColumnInfo.Parse[DataTypes.SYBDATETIME](data, pos)
end,
[DataTypes.SYBINT4] = function( data, pos ) [DataTypes.SYBINT4] = function( data, pos )
return ColumnInfo.Parse[DataTypes.SYBDATETIME](data, pos) return ColumnInfo.Parse[DataTypes.SYBDATETIME](data, pos)
end, end,
[DataTypes.XSYBVARBINARY] = function( data, pos )
local colinfo = {}
local tmp
pos, colinfo.lts, colinfo.msglen = bin.unpack("<SC", data, pos)
pos, tmp = bin.unpack("A" .. (colinfo.msglen * 2), data, pos )
colinfo.text = Util.FromWideChar(tmp)
return pos, colinfo
end,
[DataTypes.SYBDATETIME] = function( data, pos ) [DataTypes.SYBDATETIME] = function( data, pos )
local colinfo = {} local colinfo = {}
local tmp local tmp
@@ -780,15 +795,82 @@ ColumnInfo =
return pos, colinfo return pos, colinfo
end, end,
[DataTypes.NTEXTTYPE] = function( data, pos )
return ColumnInfo.Parse[DataTypes.SQLTEXT](data, pos)
end,
[DataTypes.BITNTYPE] = function( data, pos )
return ColumnInfo.Parse[DataTypes.SYBINTN](data, pos)
end,
[DataTypes.DECIMALNTYPE] = function( data, pos )
local colinfo = {}
local tmp
pos, colinfo.unknown, colinfo.precision, colinfo.scale = bin.unpack("<CCC", data, pos)
pos, colinfo.msglen = bin.unpack("<C",data,pos)
pos, tmp = bin.unpack("A" .. (colinfo.msglen * 2), data, pos )
colinfo.text = Util.FromWideChar(tmp)
return pos, colinfo
end,
[DataTypes.NUMERICNTYPE] = function( data, pos )
return ColumnInfo.Parse[DataTypes.DECIMALNTYPE](data, pos)
end,
[DataTypes.FLTNTYPE] = function( data, pos )
return ColumnInfo.Parse[DataTypes.SYBINTN](data, pos)
end,
[DataTypes.MONEYNTYPE] = function( data, pos )
return ColumnInfo.Parse[DataTypes.SYBINTN](data, pos)
end,
[DataTypes.SYBDATETIMN] = function( data, pos ) [DataTypes.SYBDATETIMN] = function( data, pos )
return ColumnInfo.Parse[DataTypes.SYBINTN](data, pos) return ColumnInfo.Parse[DataTypes.SYBINTN](data, pos)
end, end,
[DataTypes.XSYBVARBINARY] = function( data, pos )
local colinfo = {}
local tmp
pos, colinfo.lts, colinfo.msglen = bin.unpack("<SC", data, pos)
pos, tmp = bin.unpack("A" .. (colinfo.msglen * 2), data, pos )
colinfo.text = Util.FromWideChar(tmp)
return pos, colinfo
end,
[DataTypes.XSYBVARCHAR] = function( data, pos ) [DataTypes.XSYBVARCHAR] = function( data, pos )
return ColumnInfo.Parse[DataTypes.XSYBNVARCHAR](data, pos) return ColumnInfo.Parse[DataTypes.XSYBNVARCHAR](data, pos)
end, end,
[DataTypes.BIGBINARYTYPE] = function( data, pos )
return ColumnInfo.Parse[DataTypes.XSYBVARBINARY](data, pos)
end,
[DataTypes.BIGCHARTYPE] = function( data, pos )
return ColumnInfo.Parse[DataTypes.XSYBNVARCHAR](data, pos)
end,
[DataTypes.XSYBNVARCHAR] = function( data, pos )
local colinfo = {}
local tmp
pos, colinfo.lts, colinfo.codepage, colinfo.flags, colinfo.charset,
colinfo.msglen = bin.unpack("<SSSCC", data, pos )
pos, tmp = bin.unpack("A" .. (colinfo.msglen * 2), data, pos)
colinfo.text = Util.FromWideChar(tmp)
return pos, colinfo
end,
[DataTypes.SQLNCHAR] = function( data, pos )
return ColumnInfo.Parse[DataTypes.XSYBNVARCHAR](data, pos)
end,
} }
} }
@@ -797,32 +879,92 @@ ColumnInfo =
ColumnData = ColumnData =
{ {
Parse = { Parse = {
[DataTypes.XSYBNVARCHAR] = function( data, pos )
local size, coldata
pos, size = bin.unpack( "<S", data, pos )
pos, coldata = bin.unpack( "A"..size, data, pos )
return pos, Util.FromWideChar(coldata) [DataTypes.SQLTEXT] = function( data, pos )
end, local len, coldata
[DataTypes.XSYBVARCHAR] = function( data, pos )
local size, coldata
pos, size = bin.unpack( "<S", data, pos ) -- The first len value is the size of the meta data block
pos, coldata = bin.unpack( "A"..size, data, pos ) -- for non-null values this seems to be 0x10 / 16 bytes
pos, len = bin.unpack( "<C", data, pos )
if ( len == 0 ) then
return pos, 'Null'
end
-- Skip over the text update time and date values, we don't need them
-- We may come back add parsing for this information.
pos = pos + len
-- skip a label, should be 'dummyTS'
pos = pos + 8
-- extract the actual data
pos, len = bin.unpack( "<I", data, pos )
pos, coldata = bin.unpack( "A"..len, data, pos )
return pos, coldata return pos, coldata
end, end,
[DataTypes.XSYBVARBINARY] = function( data, pos ) [DataTypes.GUIDTYPE] = function( data, pos )
local coldata, size local len, coldata, index, nextdata
local hex = {}
pos, size = bin.unpack( "<S", data, pos ) pos, len = bin.unpack("C", data, pos)
pos, coldata = bin.unpack( "A"..size, data, pos )
return pos, "0x" .. select(2, bin.unpack("H"..coldata:len(), coldata ) ) if ( len == 0 ) then
return pos, 'Null'
elseif ( len == 16 ) then
-- Return the first 8 bytes
for index=1, 8 do
pos, hex[index] = bin.unpack("H", data, pos)
end
-- reorder the bytes
coldata = hex[4] .. hex[3] .. hex[2] .. hex[1]
coldata = coldata .. '-' .. hex[6] .. hex[5]
coldata = coldata .. '-' .. hex[8] .. hex[7]
pos, nextdata = bin.unpack("H2", data, pos)
coldata = coldata .. '-' .. nextdata
pos, nextdata = bin.unpack("H6", data, pos)
coldata = coldata .. '-' .. nextdata
else
stdnse.print_debug("Unhandled length (%d) for GUIDTYPE", len)
return pos + len, 'Unsupported Data'
end
return pos, coldata
end,
[DataTypes.SYBINTN] = function( data, pos )
local len, num
pos, len = bin.unpack("C", data, pos)
if ( len == 0 ) then
return pos, 'Null'
elseif ( len == 1 ) then
return bin.unpack("C", data, pos)
elseif ( len == 2 ) then
return bin.unpack("<s", data, pos)
elseif ( len == 4 ) then
return bin.unpack("<i", data, pos)
elseif ( len == 8 ) then
return bin.unpack("<l", data, pos)
else
return -1, ("Unhandled length (%d) for SYBINTN"):format(len)
end
return -1, "Error"
end,
[DataTypes.SYBINT2] = function( data, pos )
local num
pos, num = bin.unpack("<S", data, pos)
return pos, num
end, end,
[DataTypes.SYBINT4] = function( data, pos ) [DataTypes.SYBINT4] = function( data, pos )
@@ -832,45 +974,257 @@ ColumnData =
return pos, num return pos, num
end, end,
[DataTypes.SYBINT2] = function( data, pos ) [DataTypes.SYBDATETIME] = function( data, pos )
local num local hi, lo, result_seconds, result
pos, num = bin.unpack("<S", data, pos) local tds_epoch, system_epoch, tds_offset_seconds
pos, hi, lo = bin.unpack("<iI", data, pos)
tds_epoch = os.time( {year = 1900, month = 1, day = 1, hour = 00, min = 00, sec = 00, isdst = nil} )
-- determine the offset between the tds_epoch and the local system epoch
system_epoch = os.time( os.date("*t", 0))
tds_offset_seconds = os.difftime(tds_epoch,system_epoch)
result_seconds = (hi*24*60*60) + (lo/300)
result = os.date("!%b %d, %Y %H:%M:%S", tds_offset_seconds + result_seconds )
return pos, result
end,
[DataTypes.NTEXTTYPE] = function( data, pos )
local len, coldata
-- The first len value is the size of the meta data block
pos, len = bin.unpack( "<C", data, pos )
if ( len == 0 ) then
return pos, 'Null'
end
-- Skip over the text update time and date values, we don't need them
-- We may come back add parsing for this information.
pos = pos + len
-- skip a label, should be 'dummyTS'
pos = pos + 8
-- extract the actual data
pos, len = bin.unpack( "<I", data, pos )
pos, coldata = bin.unpack( "A"..len, data, pos )
return pos, Util.FromWideChar(coldata)
end,
[DataTypes.BITNTYPE] = function( data, pos )
return ColumnData.Parse[DataTypes.SYBINTN](data, pos)
end,
[DataTypes.DECIMALNTYPE] = function( precision, scale, data, pos )
local len, sign, format_string, coldata
pos, len = bin.unpack("<C", data, pos)
if ( len == 0 ) then
return pos, 'Null'
end
pos, sign = bin.unpack("<C", data, pos)
-- subtract 1 from data len to account for sign byte
len = len - 1
if ( len == 2 ) then
pos, coldata = bin.unpack("<S", data, pos)
elseif ( len == 4 ) then
pos, coldata = bin.unpack("<I", data, pos)
elseif ( len == 8 ) then
pos, coldata = bin.unpack("<L", data, pos)
else
stdnse.print_debug("Unhandled length (%d) for DECIMALNTYPE", len)
return pos + len, 'Unsupported Data'
end
if ( sign == 0 ) then
coldata = coldata * -1
end
return pos, num coldata = coldata * (10^-scale)
-- format the return information to reduce truncation by lua
format_string = string.format("%%.%if", scale)
coldata = string.format(format_string,coldata)
return pos, coldata
end, end,
[DataTypes.SYBINTN] = function( data, pos ) [DataTypes.NUMERICNTYPE] = function( precision, scale, data, pos )
local len, num return ColumnData.Parse[DataTypes.DECIMALNTYPE]( precision, scale, data, pos )
end,
[DataTypes.SYBDATETIME] = function( data, pos )
local hi, lo, result_seconds, result
local tds_epoch, system_epoch, tds_offset_seconds
pos, hi, lo = bin.unpack("<iI", data, pos)
tds_epoch = os.time( {year = 1900, month = 1, day = 1, hour = 00, min = 00, sec = 00, isdst = nil} )
-- determine the offset between the tds_epoch and the local system epoch
system_epoch = os.time( os.date("*t", 0))
tds_offset_seconds = os.difftime(tds_epoch,system_epoch)
result_seconds = (hi*24*60*60) + (lo/300)
result = os.date("!%b %d, %Y %H:%M:%S", tds_offset_seconds + result_seconds )
return pos, result
end,
[DataTypes.BITNTYPE] = function( data, pos )
return ColumnData.Parse[DataTypes.SYBINTN](data, pos)
end,
[DataTypes.NTEXTTYPE] = function( data, pos )
local len, coldata
-- The first len value is the size of the meta data block
pos, len = bin.unpack( "<C", data, pos )
if ( len == 0 ) then
return pos, 'Null'
end
-- Skip over the text update time and date values, we don't need them
-- We may come back add parsing for this information.
pos = pos + len
-- skip a label, should be 'dummyTS'
pos = pos + 8
-- extract the actual data
pos, len = bin.unpack( "<I", data, pos )
pos, coldata = bin.unpack( "A"..len, data, pos )
return pos, Util.FromWideChar(coldata)
end,
[DataTypes.FLTNTYPE] = function( data, pos )
local len, coldata
pos, len = bin.unpack("<C", data, pos)
if ( len == 0 ) then
return pos, 'Null'
elseif ( len == 4 ) then
pos, coldata = bin.unpack("f", data, pos)
elseif ( len == 8 ) then
pos, coldata = bin.unpack("<d", data, pos)
end
return pos, coldata
end,
[DataTypes.MONEYNTYPE] = function( data, pos )
local len, value, coldata, hi, lo
pos, len = bin.unpack("C", data, pos) pos, len = bin.unpack("C", data, pos)
if ( len == 1 ) then if ( len == 0 ) then
return bin.unpack("C", data, pos) return pos, 'Null'
elseif ( len == 2 ) then elseif ( len == 4 ) then
return bin.unpack("<S", data, pos) --type smallmoney
elseif ( len == 4 ) then pos, value = bin.unpack("<i", data, pos)
return bin.unpack("<I", data, pos)
elseif ( len == 8 ) then elseif ( len == 8 ) then
return bin.unpack("<L", data, pos) -- type money
pos, hi,lo = bin.unpack("<II", data, pos)
value = ( hi * 4294967296 ) + lo
else else
return -1, ("Unhandled length (%d) for SYBINTN"):format(len) return -1, ("Unhandled length (%d) for MONEYNTYPE"):format(len)
end
-- the datatype allows for 4 decimal places after the period to support various currency types.
-- forcing to string to avoid truncation
coldata = string.format("%.4f",value/10000)
return pos, coldata
end,
[DataTypes.SYBDATETIMN] = function( data, pos )
local len, coldata
pos, len = bin.unpack( "<C", data, pos )
if ( len == 0 ) then
return pos, 'Null'
elseif ( len == 4 ) then
-- format is smalldatetime
local days, mins
pos, days, mins = bin.unpack("<SS", data, pos)
tds_epoch = os.time( {year = 1900, month = 1, day = 1, hour = 00, min = 00, sec = 00, isdst = nil} )
-- determine the offset between the tds_epoch and the local system epoch
system_epoch = os.time( os.date("*t", 0))
tds_offset_seconds = os.difftime(tds_epoch,system_epoch)
result_seconds = (days*24*60*60) + (mins*60)
coldata = os.date("!%b %d, %Y %H:%M:%S", tds_offset_seconds + result_seconds )
return pos,coldata
elseif ( len == 8 ) then
-- format is datetime
return ColumnData.Parse[DataTypes.SYBDATETIME](data, pos)
else
return -1, ("Unhandled length (%d) for SYBDATETIMN"):format(len)
end
end,
[DataTypes.XSYBVARBINARY] = function( data, pos )
local len, coldata
pos, len = bin.unpack( "<S", data, pos )
if ( len == 65535 ) then
return pos, 'Null'
else
pos, coldata = bin.unpack( "A"..len, data, pos )
return pos, "0x" .. select(2, bin.unpack("H"..coldata:len(), coldata ) )
end end
return -1, "Error" return -1, "Error"
end, end,
[DataTypes.SYBDATETIME] = function( data, pos ) [DataTypes.XSYBVARCHAR] = function( data, pos )
local hi, lo, dt, result local len, coldata
pos, hi, lo = bin.unpack("<II", data, pos)
-- CET 01/01/1900 pos, len = bin.unpack( "<S", data, pos )
dt = -2208996000 if ( len == 65535 ) then
result = os.date("%x %X", dt + (hi*24*60*60) + (lo/300) ) return pos, 'Null'
end
return pos, result
pos, coldata = bin.unpack( "A"..len, data, pos )
return pos, coldata
end, end,
[DataTypes.SYBDATETIMN] = function( data, pos ) [DataTypes.BIGBINARYTYPE] = function( data, pos )
return ColumnData.Parse[DataTypes.SYBINTN]( data, pos ) return ColumnData.Parse[DataTypes.XSYBVARBINARY](data, pos)
end,
[DataTypes.BIGCHARTYPE] = function( data, pos )
return ColumnData.Parse[DataTypes.XSYBVARCHAR](data, pos)
end,
[DataTypes.XSYBNVARCHAR] = function( data, pos )
local len, coldata
pos, len = bin.unpack( "<S", data, pos )
if ( len == 65535 ) then
return pos, 'Null'
end
pos, coldata = bin.unpack( "A"..len, data, pos )
return pos, Util.FromWideChar(coldata)
end,
[DataTypes.SQLNCHAR] = function( data, pos )
return ColumnData.Parse[DataTypes.XSYBNVARCHAR](data, pos)
end, end,
} }
@@ -967,6 +1321,21 @@ Token =
return pos, token return pos, token
end, end,
--- Parses a DoneProc token recieved after executing a SP
--
-- @param data string containing "raw" data
-- @param pos number containing offset into data
-- @return pos number containing new offset after parse
-- @return token table containing token specific fields
[TokenType.DoneProc] = function( data, pos )
local token
pos, token = Token.Parse[TokenType.Done]( data, pos )
token.type = TokenType.DoneProc
return pos, token
end,
--- Parses a DoneInProc token recieved after executing a SP --- Parses a DoneInProc token recieved after executing a SP
-- --
@@ -1020,22 +1389,21 @@ Token =
[TokenType.TDS7Results] = function( data, pos ) [TokenType.TDS7Results] = function( data, pos )
local token = {} local token = {}
local _ local _
token.type = TokenType.TDS7Results token.type = TokenType.TDS7Results
pos, token.count = bin.unpack( "<S", data, pos ) pos, token.count = bin.unpack( "<S", data, pos )
token.colinfo = {} token.colinfo = {}
for i=1, token.count do for i=1, token.count do
local colinfo = {} local colinfo = {}
local usertype, flags, ttype local usertype, flags, ttype
pos, usertype, flags, ttype = bin.unpack("<SSC", data, pos ) pos, usertype, flags, ttype = bin.unpack("<SSC", data, pos )
if ( not(ColumnInfo.Parse[ttype]) ) then if ( not(ColumnInfo.Parse[ttype]) ) then
return -1, ("Unhandled data type: 0x%X"):format(ttype) return -1, ("Unhandled data type: 0x%X"):format(ttype)
end end
pos, colinfo = ColumnInfo.Parse[ttype]( data, pos ) pos, colinfo = ColumnInfo.Parse[ttype]( data, pos )
colinfo.usertype = usertype colinfo.usertype = usertype
colinfo.flags = flags colinfo.flags = flags
colinfo.type = ttype colinfo.type = ttype
@@ -2423,7 +2791,13 @@ Helper =
local val local val
if ( ColumnData.Parse[colinfo[i].type] ) then if ( ColumnData.Parse[colinfo[i].type] ) then
pos, val = ColumnData.Parse[colinfo[i].type](data, pos) if not ( colinfo[i].type == 106 or colinfo[i].type == 108) then
pos, val = ColumnData.Parse[colinfo[i].type](data, pos)
else
-- decimal / numeric types need precision and scale passed.
pos, val = ColumnData.Parse[colinfo[i].type]( colinfo[i].precision, colinfo[i].scale, data, pos)
end
if ( -1 == pos ) then if ( -1 == pos ) then
return false, val return false, val
end end