Skip to content

Commit c681ed0

Browse files
committed
Match Sybase dblib's handling of overlong or malformatted BCP input.
Adjust existing failure modes' boundaries and introduce the possibility of proceeding with truncated input but reporting a message (20074, aka SYBEBCOR) as a middle ground between silent truncation and noisy failure. To that end, pass _bcp_convert_in the destination's length. Signed-off-by: Aaron M. Ucko <[email protected]>
1 parent 221cfc2 commit c681ed0

File tree

1 file changed

+49
-6
lines changed

1 file changed

+49
-6
lines changed

src/dblib/bcp.c

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <stdarg.h>
2424
#include <stdio.h>
2525
#include <assert.h>
26+
#include <ctype.h>
2627

2728
#if HAVE_STRING_H
2829
#include <string.h>
@@ -1053,8 +1054,10 @@ _bcp_check_eof(DBPROCESS * dbproc, FILE *file, int icol)
10531054
* Convert column for input to a table
10541055
*/
10551056
static TDSRET
1056-
_bcp_convert_in(DBPROCESS *dbproc, TDS_SERVER_TYPE srctype, const TDS_CHAR *src, TDS_UINT srclen,
1057-
TDS_SERVER_TYPE desttype, BCPCOLDATA *coldata)
1057+
_bcp_convert_in(DBPROCESS *dbproc, TDS_SERVER_TYPE srctype,
1058+
const TDS_CHAR *src, TDS_UINT srclen,
1059+
TDS_SERVER_TYPE desttype, BCPCOLDATA *coldata,
1060+
TDS_UINT destlen)
10581061
{
10591062
bool variable = true;
10601063
CONV_RESULT cr, *p_cr;
@@ -1070,9 +1073,45 @@ _bcp_convert_in(DBPROCESS *dbproc, TDS_SERVER_TYPE srctype, const TDS_CHAR *src,
10701073
}
10711074

10721075
len = tds_convert(dbproc->tds_socket->conn->tds_ctx, srctype, src, srclen, desttype, p_cr);
1076+
if (len == TDS_CONVERT_SYNTAX && is_binary_type(desttype)) {
1077+
char * s = (char *) src;
1078+
int srclen2 = destlen * 2;
1079+
if (srclen > 1 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
1080+
srclen2 += 2;
1081+
/* Match full input's low order bit to get correct phase. */
1082+
if (srclen & 1)
1083+
--srclen2;
1084+
if (srclen2 < srclen) {
1085+
len = tds_convert(dbproc->tds_socket->conn->tds_ctx,
1086+
srctype, src, srclen2, desttype,
1087+
p_cr);
1088+
}
1089+
/*
1090+
* Check the last character to avoid interference from
1091+
* space and NUL stripping.
1092+
*/
1093+
if (len == destlen && isxdigit(s[srclen2 - 1])) {
1094+
free(p_cr->ib);
1095+
dbperror(dbproc, SYBECOFL, 0);
1096+
return TDS_FAIL;
1097+
} else {
1098+
if (len >= 0)
1099+
free(p_cr->ib);
1100+
len = TDS_CONVERT_SYNTAX;
1101+
}
1102+
}
10731103
if (len < 0) {
10741104
_dblib_convert_err(dbproc, len);
10751105
return TDS_FAIL;
1106+
} else if (len > destlen) {
1107+
if ((is_binary_type(srctype) && is_binary_type(desttype))
1108+
|| (is_char_type(srctype) && is_char_type(desttype))) {
1109+
dbperror(dbproc, SYBEBCOR, 0);
1110+
/* Proceed anyway */
1111+
} else {
1112+
dbperror(dbproc, SYBECOFL, 0);
1113+
return TDS_FAIL;
1114+
}
10761115
}
10771116

10781117
coldata->datalen = len;
@@ -1336,8 +1375,11 @@ _bcp_read_hostfile(DBPROCESS * dbproc, FILE * hostfile, bool *row_error, bool sk
13361375

13371376
desttype = tds_get_conversion_type(bcpcol->column_type, bcpcol->column_size);
13381377

1339-
rc = _bcp_convert_in(dbproc, hostcol->datatype, (const TDS_CHAR*) coldata, collen,
1340-
desttype, bcpcol->bcp_column_data);
1378+
rc = _bcp_convert_in(dbproc, hostcol->datatype,
1379+
(const TDS_CHAR*) coldata,
1380+
collen, desttype,
1381+
bcpcol->bcp_column_data,
1382+
bcpcol->column_size);
13411383
if (TDS_FAILED(rc)) {
13421384
hostcol->column_error = HOST_COL_CONV_ERROR;
13431385
*row_error = true;
@@ -2258,8 +2300,9 @@ _bcp_get_col_data(TDSBCPINFO *bcpinfo, TDSCOLUMN *bindcol, int offset TDS_UNUSED
22582300
if (collen < 0)
22592301
collen = (int) strlen((char *) dataptr);
22602302

2261-
rc = _bcp_convert_in(dbproc, coltype, (const TDS_CHAR*) dataptr, collen,
2262-
desttype, bindcol->bcp_column_data);
2303+
rc = _bcp_convert_in(dbproc, coltype, (const TDS_CHAR*) dataptr,
2304+
collen, desttype, bindcol->bcp_column_data,
2305+
bindcol->column_size);
22632306
if (TDS_FAILED(rc))
22642307
return rc;
22652308
rtrim_bcpcol(bindcol);

0 commit comments

Comments
 (0)