Refine memory allocation in ICU conversions

The simple calculations done to estimate the size of the output buffers
for ucnv_fromUChars() and ucnv_toUChars() could overflow int32_t for
large strings.  To avoid that, go the long way and run the function
first without an output buffer to get the correct output buffer size
requirement.
pull/23/head
Peter Eisentraut 9 years ago
parent b0f069d931
commit d8b3c81335
  1. 24
      src/backend/utils/adt/pg_locale.c

@ -1511,14 +1511,22 @@ icu_to_uchar(UChar **buff_uchar, const char *buff, size_t nbytes)
init_icu_converter();
len_uchar = 2 * nbytes + 1; /* max length per docs */
*buff_uchar = palloc(len_uchar * sizeof(**buff_uchar));
status = U_ZERO_ERROR;
len_uchar = ucnv_toUChars(icu_converter, *buff_uchar, len_uchar,
len_uchar = ucnv_toUChars(icu_converter, NULL, 0,
buff, nbytes, &status);
if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR)
ereport(ERROR,
(errmsg("ucnv_toUChars failed: %s", u_errorName(status))));
*buff_uchar = palloc((len_uchar + 1) * sizeof(**buff_uchar));
status = U_ZERO_ERROR;
len_uchar = ucnv_toUChars(icu_converter, *buff_uchar, len_uchar + 1,
buff, nbytes, &status);
if (U_FAILURE(status))
ereport(ERROR,
(errmsg("ucnv_toUChars failed: %s", u_errorName(status))));
return len_uchar;
}
@ -1541,14 +1549,22 @@ icu_from_uchar(char **result, const UChar *buff_uchar, int32_t len_uchar)
init_icu_converter();
len_result = UCNV_GET_MAX_BYTES_FOR_STRING(len_uchar, ucnv_getMaxCharSize(icu_converter));
status = U_ZERO_ERROR;
len_result = ucnv_fromUChars(icu_converter, NULL, 0,
buff_uchar, len_uchar, &status);
if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR)
ereport(ERROR,
(errmsg("ucnv_fromUChars failed: %s", u_errorName(status))));
*result = palloc(len_result + 1);
status = U_ZERO_ERROR;
len_result = ucnv_fromUChars(icu_converter, *result, len_result + 1,
buff_uchar, len_uchar, &status);
if (U_FAILURE(status))
ereport(ERROR,
(errmsg("ucnv_fromUChars failed: %s", u_errorName(status))));
return len_result;
}
#endif /* USE_ICU */

Loading…
Cancel
Save