Line data Source code
1 : /*
2 : * Purpose: Test that a string truncated inside a multibyte sequence is reported
3 : * correctly, reporting the error used to crash, see GitHub issue #227.
4 : * The server truncates a surrogate pair storing it in a NVARCHAR(1) column.
5 : */
6 :
7 : #include "common.h"
8 :
9 : static int conversion_errors = 0;
10 : static int wrong_errors = 0;
11 :
12 : static int
13 8 : err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
14 : {
15 8 : switch (dberr) {
16 8 : case SYBEICONVPARTIAL:
17 : case SYBEICONVI:
18 8 : printf("got expected error %d: %s\n", dberr, dberrstr);
19 8 : ++conversion_errors;
20 8 : return INT_CANCEL;
21 0 : case SYBEICONVAVAIL:
22 0 : fprintf(stderr, "conversion wrongly reported as not available: %s\n", dberrstr);
23 0 : ++wrong_errors;
24 0 : return INT_CANCEL;
25 : default:
26 : break;
27 : }
28 0 : return syb_err_handler(dbproc, severity, dberr, oserr, dberrstr, oserrstr);
29 : }
30 :
31 10 : TEST_MAIN()
32 : {
33 : LOGINREC *login;
34 : DBPROCESS *dbproc;
35 10 : DBINT value = 0;
36 :
37 10 : set_malloc_options();
38 :
39 10 : read_login_info(argc, argv);
40 :
41 10 : dbinit();
42 :
43 10 : dberrhandle(err_handler);
44 10 : dbmsghandle(syb_msg_handler);
45 :
46 10 : login = dblogin();
47 10 : DBSETLPWD(login, PASSWORD);
48 10 : DBSETLUSER(login, USER);
49 10 : DBSETLAPP(login, "iconv_partial");
50 :
51 10 : dbproc = dbopen(login, SERVER);
52 10 : if (!dbproc) {
53 0 : fprintf(stderr, "Unable to connect to %s\n", SERVER);
54 0 : return 1;
55 : }
56 10 : dbloginfree(login);
57 :
58 : /* requires an UTF-16 column from Microsoft server */
59 10 : if (dbtds(dbproc) < DBTDS_7_0) {
60 2 : dbclose(dbproc);
61 2 : dbexit();
62 2 : return 77;
63 : }
64 :
65 8 : dbcmd(dbproc, "DECLARE @test NVARCHAR(1) SET @test = 0x3CD884DF SELECT @test AS test, 1234 AS n");
66 8 : if (dbsqlexec(dbproc) != SUCCEED) {
67 0 : fprintf(stderr, "error: executing query\n");
68 0 : return 1;
69 : }
70 :
71 : /* DECLARE can produce a result without columns, skip it */
72 : do {
73 16 : if (dbresults(dbproc) != SUCCEED) {
74 0 : fprintf(stderr, "error: expected a result set\n");
75 0 : return 1;
76 : }
77 16 : } while (dbnumcols(dbproc) == 0);
78 :
79 8 : if (dbbind(dbproc, 2, INTBIND, -1, (BYTE *) & value) != SUCCEED) {
80 0 : fprintf(stderr, "error: binding column\n");
81 0 : return 1;
82 : }
83 :
84 8 : if (dbnextrow(dbproc) != REG_ROW) {
85 0 : fprintf(stderr, "error: expected a row\n");
86 0 : return 1;
87 : }
88 :
89 : /* the conversion problem should not affect the following column */
90 8 : if (value != 1234) {
91 0 : fprintf(stderr, "error: unexpected value %d\n", (int) value);
92 0 : return 1;
93 : }
94 :
95 8 : dbcancel(dbproc);
96 8 : dbclose(dbproc);
97 8 : dbexit();
98 :
99 8 : if (wrong_errors || !conversion_errors) {
100 0 : fprintf(stderr, "error: wrong conversion errors %d, right conversion errors %d\n", wrong_errors, conversion_errors);
101 0 : return 1;
102 : }
103 :
104 8 : printf("OK\n");
105 8 : return 0;
106 : }
|