/ Check-in [b8dc1b9f]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix a potential buffer overflow in the ICU upper() function.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:b8dc1b9f5d413000387bfe784b69f5d0ee5c0489
User & Date: drh 2016-02-26 21:20:57
Context
2016-02-26
23:13
Support generating the '.def' file using the autoconf Makefile for MSVC. check-in: 3617564c user: mistachkin tags: trunk
21:20
Fix a potential buffer overflow in the ICU upper() function. check-in: b8dc1b9f user: drh tags: trunk
21:03
Further refinements to the MSVC batch build process. check-in: cf4e4fbd user: mistachkin tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ext/icu/icu.c.

351
352
353
354
355
356
357
358
359
360
361

362
363
364
365
366
367
368
369
370
371
372
373
374



375
376
377




378

379
380
381


382
383

384
385

386
387
388

389

390
391
392
393
394
395
396
397
398
399
400
**     lower('I', 'en_us') -> 'i'
**     lower('I', 'tr_tr') -> 'ı' (small dotless i)
**
** http://www.icu-project.org/userguide/posix.html#case_mappings
*/
static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
  const UChar *zInput;
  UChar *zOutput;
  int nInput;
  int nOutput;


  UErrorCode status = U_ZERO_ERROR;
  const char *zLocale = 0;

  assert(nArg==1 || nArg==2);
  if( nArg==2 ){
    zLocale = (const char *)sqlite3_value_text(apArg[1]);
  }

  zInput = sqlite3_value_text16(apArg[0]);
  if( !zInput ){
    return;
  }
  nInput = sqlite3_value_bytes16(apArg[0]);




  nOutput = nInput * 2 + 2;
  zOutput = sqlite3_malloc(nOutput);




  if( !zOutput ){

    return;
  }



  if( sqlite3_user_data(p) ){
    u_strToUpper(zOutput, nOutput/2, zInput, nInput/2, zLocale, &status);

  }else{
    u_strToLower(zOutput, nOutput/2, zInput, nInput/2, zLocale, &status);

  }

  if( !U_SUCCESS(status) ){

    icuFunctionError(p, "u_strToLower()/u_strToUpper", status);

    return;
  }

  sqlite3_result_text16(p, zOutput, -1, xFree);
}

/*
** Collation sequence destructor function. The pCtx argument points to
** a UCollator structure previously allocated using ucol_open().
*/
static void icuCollationDel(void *pCtx){







|

|
<
>
|











|
>
>
>
|
<
<
>
>
>
>
|
>
|
|
<
>
>
|
<
>
|
<
>
|
<
|
>
|
>
|
|
|
|







351
352
353
354
355
356
357
358
359
360

361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378


379
380
381
382
383
384
385
386

387
388
389

390
391

392
393

394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
**     lower('I', 'en_us') -> 'i'
**     lower('I', 'tr_tr') -> 'ı' (small dotless i)
**
** http://www.icu-project.org/userguide/posix.html#case_mappings
*/
static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
  const UChar *zInput;
  UChar *zOutput = 0;
  int nInput;
  int nOut;

  int cnt;
  UErrorCode status;
  const char *zLocale = 0;

  assert(nArg==1 || nArg==2);
  if( nArg==2 ){
    zLocale = (const char *)sqlite3_value_text(apArg[1]);
  }

  zInput = sqlite3_value_text16(apArg[0]);
  if( !zInput ){
    return;
  }
  nOut = nInput = sqlite3_value_bytes16(apArg[0]);
  if( nOut==0 ){
    sqlite3_result_text16(p, "", 0, SQLITE_STATIC);
    return;
  }



  for(cnt=0; cnt<2; cnt++){
    UChar *zNew = sqlite3_realloc(zOutput, nOut);
    if( zNew==0 ){
      sqlite3_free(zOutput);
      sqlite3_result_error_nomem(p);
      return;
    }

    zOutput = zNew;
    status = U_ZERO_ERROR;
    if( sqlite3_user_data(p) ){

      nOut = 2*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
    }else{

      nOut = 2*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
    }

    if( !U_SUCCESS(status) ){
      if( status==U_BUFFER_OVERFLOW_ERROR ) continue;
      icuFunctionError(p,
          sqlite3_user_data(p) ? "u_strToUpper()" : "u_strToLower", status);
      return;
    }
  }
  sqlite3_result_text16(p, zOutput, nOut, xFree);
}

/*
** Collation sequence destructor function. The pCtx argument points to
** a UCollator structure previously allocated using ucol_open().
*/
static void icuCollationDel(void *pCtx){

Changes to test/icu.test.

67
68
69
70
71
72
73




74
75
76
77
78
79
80
...
129
130
131
132
133
134
135





136
test_expr icu-2.3 {i1=$::EGRAVE} {lower(i1)}     $::egrave
test_expr icu-2.4 {i1=$::EGRAVE} {upper(i1)}     $::EGRAVE
test_expr icu-2.5 {i1=$::OGRAVE} {lower(i1)}     $::ograve
test_expr icu-2.6 {i1=$::OGRAVE} {upper(i1)}     $::OGRAVE

test_expr icu-2.7 {i1=$::szlig} {upper(i1)}      "SS"
test_expr icu-2.8 {i1='SS'} {lower(i1)}          "ss"





# In turkish (locale="tr_TR"), the lower case version of I
# is "small dotless i" (code point 0x131 (decimal 305)).
#
set ::small_dotless_i "\u0131"
test_expr icu-3.1 {i1='I'} {lower(i1)}           "i"
test_expr icu-3.2 {i1='I'} {lower(i1, 'tr_tr')}  $::small_dotless_i
................................................................................
} {1 {wrong number of arguments to function regexp()}}
do_catchsql_test icu-5.4 { 
  SELECT 'abc' REGEXP 'a[abc]c.*'
} {0 1}
do_catchsql_test icu-5.4 { SELECT 'abc' REGEXP }    {1 {near " ": syntax error}}
do_catchsql_test icu-5.5 { SELECT 'abc' REGEXP, 1 } {1 {near ",": syntax error}}






finish_test







>
>
>
>







 







>
>
>
>
>

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
...
133
134
135
136
137
138
139
140
141
142
143
144
145
test_expr icu-2.3 {i1=$::EGRAVE} {lower(i1)}     $::egrave
test_expr icu-2.4 {i1=$::EGRAVE} {upper(i1)}     $::EGRAVE
test_expr icu-2.5 {i1=$::OGRAVE} {lower(i1)}     $::ograve
test_expr icu-2.6 {i1=$::OGRAVE} {upper(i1)}     $::OGRAVE

test_expr icu-2.7 {i1=$::szlig} {upper(i1)}      "SS"
test_expr icu-2.8 {i1='SS'} {lower(i1)}          "ss"

do_execsql_test icu-2.9 {
  SELECT upper(char(0xfb04,0xfb04,0xfb04,0xfb04));
} {FFLFFLFFLFFL}

# In turkish (locale="tr_TR"), the lower case version of I
# is "small dotless i" (code point 0x131 (decimal 305)).
#
set ::small_dotless_i "\u0131"
test_expr icu-3.1 {i1='I'} {lower(i1)}           "i"
test_expr icu-3.2 {i1='I'} {lower(i1, 'tr_tr')}  $::small_dotless_i
................................................................................
} {1 {wrong number of arguments to function regexp()}}
do_catchsql_test icu-5.4 { 
  SELECT 'abc' REGEXP 'a[abc]c.*'
} {0 1}
do_catchsql_test icu-5.4 { SELECT 'abc' REGEXP }    {1 {near " ": syntax error}}
do_catchsql_test icu-5.5 { SELECT 'abc' REGEXP, 1 } {1 {near ",": syntax error}}


do_malloc_test icu-6.10 -sqlbody {
  SELECT upper(char(0xfb04,0xdf,0xfb04,0xe8,0xfb04));
}

finish_test