mirror of
https://github.com/postgres/postgres.git
synced 2025-12-01 12:18:01 +03:00
Close previously open holes for invalidly encoded data to enter the
database via builtin functions, as recently discussed on -hackers. chr() now returns a character in the database encoding. For UTF8 encoded databases the argument is treated as a Unicode code point. For other multi-byte encodings the argument must designate a strict ascii character, or an error is raised, as is also the case if the argument is 0. ascii() is adjusted so that it remains the inverse of chr(). The two argument form of convert() is gone, and the three argument form now takes a bytea first argument and returns a bytea. To cover this loss three new functions are introduced: . convert_from(bytea, name) returns text - converts the first argument from the named encoding to the database encoding . convert_to(text, name) returns bytea - converts the first argument from the database encoding to the named encoding . length(bytea, name) returns int - gives the length of the first argument in characters in the named encoding
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
* (currently mule internal code (mic) is used)
|
||||
* Tatsuo Ishii
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/utils/mb/mbutils.c,v 1.63 2007/05/28 16:43:24 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/mb/mbutils.c,v 1.64 2007/09/18 17:41:17 adunstan Exp $
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
@@ -292,12 +292,12 @@ pg_do_encoding_conversion(unsigned char *src, int len,
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert string using encoding_nanme. We assume that string's
|
||||
* encoding is same as DB encoding.
|
||||
* Convert string using encoding_name. The source
|
||||
* encoding is the DB encoding.
|
||||
*
|
||||
* TEXT convert(TEXT string, NAME encoding_name) */
|
||||
* BYTEA convert_to(TEXT string, NAME encoding_name) */
|
||||
Datum
|
||||
pg_convert(PG_FUNCTION_ARGS)
|
||||
pg_convert_to(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Datum string = PG_GETARG_DATUM(0);
|
||||
Datum dest_encoding_name = PG_GETARG_DATUM(1);
|
||||
@@ -306,7 +306,30 @@ pg_convert(PG_FUNCTION_ARGS)
|
||||
Datum result;
|
||||
|
||||
result = DirectFunctionCall3(
|
||||
pg_convert2, string, src_encoding_name, dest_encoding_name);
|
||||
pg_convert, string, src_encoding_name, dest_encoding_name);
|
||||
|
||||
/* free memory allocated by namein */
|
||||
pfree((void *) src_encoding_name);
|
||||
|
||||
PG_RETURN_BYTEA_P(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert string using encoding_name. The destination
|
||||
* encoding is the DB encoding.
|
||||
*
|
||||
* TEXT convert_from(BYTEA string, NAME encoding_name) */
|
||||
Datum
|
||||
pg_convert_from(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Datum string = PG_GETARG_DATUM(0);
|
||||
Datum src_encoding_name = PG_GETARG_DATUM(1);
|
||||
Datum dest_encoding_name = DirectFunctionCall1(
|
||||
namein, CStringGetDatum(DatabaseEncoding->name));
|
||||
Datum result;
|
||||
|
||||
result = DirectFunctionCall3(
|
||||
pg_convert, string, src_encoding_name, dest_encoding_name);
|
||||
|
||||
/* free memory allocated by namein */
|
||||
pfree((void *) src_encoding_name);
|
||||
@@ -315,20 +338,20 @@ pg_convert(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert string using encoding_name.
|
||||
* Convert string using encoding_names.
|
||||
*
|
||||
* TEXT convert2(TEXT string, NAME src_encoding_name, NAME dest_encoding_name)
|
||||
* BYTEA convert(BYTEA string, NAME src_encoding_name, NAME dest_encoding_name)
|
||||
*/
|
||||
Datum
|
||||
pg_convert2(PG_FUNCTION_ARGS)
|
||||
pg_convert(PG_FUNCTION_ARGS)
|
||||
{
|
||||
text *string = PG_GETARG_TEXT_P(0);
|
||||
bytea *string = PG_GETARG_TEXT_P(0);
|
||||
char *src_encoding_name = NameStr(*PG_GETARG_NAME(1));
|
||||
int src_encoding = pg_char_to_encoding(src_encoding_name);
|
||||
char *dest_encoding_name = NameStr(*PG_GETARG_NAME(2));
|
||||
int dest_encoding = pg_char_to_encoding(dest_encoding_name);
|
||||
unsigned char *result;
|
||||
text *retval;
|
||||
bytea *retval;
|
||||
unsigned char *str;
|
||||
int len;
|
||||
|
||||
@@ -343,8 +366,9 @@ pg_convert2(PG_FUNCTION_ARGS)
|
||||
errmsg("invalid destination encoding name \"%s\"",
|
||||
dest_encoding_name)));
|
||||
|
||||
/* make sure that source string is null terminated */
|
||||
/* make sure that source string is valid and null terminated */
|
||||
len = VARSIZE(string) - VARHDRSZ;
|
||||
pg_verify_mbstr(src_encoding,VARDATA(string),len,false);
|
||||
str = palloc(len + 1);
|
||||
memcpy(str, VARDATA(string), len);
|
||||
*(str + len) = '\0';
|
||||
@@ -354,8 +378,7 @@ pg_convert2(PG_FUNCTION_ARGS)
|
||||
elog(ERROR, "encoding conversion failed");
|
||||
|
||||
/*
|
||||
* build text data type structure. we cannot use textin() here, since
|
||||
* textin assumes that input string encoding is same as database encoding.
|
||||
* build bytea data type structure.
|
||||
*/
|
||||
len = strlen((char *) result) + VARHDRSZ;
|
||||
retval = palloc(len);
|
||||
@@ -369,7 +392,28 @@ pg_convert2(PG_FUNCTION_ARGS)
|
||||
/* free memory if allocated by the toaster */
|
||||
PG_FREE_IF_COPY(string, 0);
|
||||
|
||||
PG_RETURN_TEXT_P(retval);
|
||||
PG_RETURN_BYTEA_P(retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* get the length of the string considered as text in the specified
|
||||
* encoding. Raises an error if the data is not valid in that
|
||||
* encoding.
|
||||
*
|
||||
* INT4 length (BYTEA string, NAME src_encoding_name)
|
||||
*/
|
||||
Datum
|
||||
length_in_encoding(PG_FUNCTION_ARGS)
|
||||
{
|
||||
bytea *string = PG_GETARG_BYTEA_P(0);
|
||||
char *src_encoding_name = NameStr(*PG_GETARG_NAME(1));
|
||||
int src_encoding = pg_char_to_encoding(src_encoding_name);
|
||||
int len = VARSIZE(string) - VARHDRSZ;
|
||||
int retval;
|
||||
|
||||
retval = pg_verify_mbstr_len(src_encoding, VARDATA(string), len, false);
|
||||
PG_RETURN_INT32(retval);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
/*
|
||||
* conversion functions between pg_wchar and multibyte streams.
|
||||
* Tatsuo Ishii
|
||||
* $PostgreSQL: pgsql/src/backend/utils/mb/wchar.c,v 1.63 2007/07/12 21:17:09 tgl Exp $
|
||||
*
|
||||
* WIN1250 client encoding updated by Pavel Behal
|
||||
* $PostgreSQL: pgsql/src/backend/utils/mb/wchar.c,v 1.64 2007/09/18 17:41:17 adunstan Exp $
|
||||
*
|
||||
*/
|
||||
/* can be used in either frontend or backend */
|
||||
@@ -1435,23 +1433,37 @@ pg_database_encoding_max_length(void)
|
||||
bool
|
||||
pg_verifymbstr(const char *mbstr, int len, bool noError)
|
||||
{
|
||||
return pg_verify_mbstr(GetDatabaseEncoding(), mbstr, len, noError);
|
||||
return
|
||||
pg_verify_mbstr_len(GetDatabaseEncoding(), mbstr, len, noError) >= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify mbstr to make sure that it is validly encoded in the specified
|
||||
* encoding.
|
||||
*
|
||||
* mbstr is not necessarily zero terminated; length of mbstr is
|
||||
* specified by len.
|
||||
*
|
||||
* If OK, return TRUE. If a problem is found, return FALSE when noError is
|
||||
* true; when noError is false, ereport() a descriptive message.
|
||||
*/
|
||||
bool
|
||||
pg_verify_mbstr(int encoding, const char *mbstr, int len, bool noError)
|
||||
{
|
||||
return pg_verify_mbstr_len(encoding, mbstr, len, noError) >= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify mbstr to make sure that it is validly encoded in the specified
|
||||
* encoding.
|
||||
*
|
||||
* mbstr is not necessarily zero terminated; length of mbstr is
|
||||
* specified by len.
|
||||
*
|
||||
* If OK, return length of string in the encoding.
|
||||
* If a problem is found, return -1 when noError is
|
||||
* true; when noError is false, ereport() a descriptive message.
|
||||
*/
|
||||
int
|
||||
pg_verify_mbstr_len(int encoding, const char *mbstr, int len, bool noError)
|
||||
{
|
||||
mbverifier mbverify;
|
||||
int mb_len;
|
||||
|
||||
Assert(PG_VALID_ENCODING(encoding));
|
||||
|
||||
@@ -1463,14 +1475,16 @@ pg_verify_mbstr(int encoding, const char *mbstr, int len, bool noError)
|
||||
const char *nullpos = memchr(mbstr, 0, len);
|
||||
|
||||
if (nullpos == NULL)
|
||||
return true;
|
||||
return len;
|
||||
if (noError)
|
||||
return false;
|
||||
return -1;
|
||||
report_invalid_encoding(encoding, nullpos, 1);
|
||||
}
|
||||
|
||||
/* fetch function pointer just once */
|
||||
mbverify = pg_wchar_table[encoding].mbverify;
|
||||
|
||||
mb_len = 0;
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
@@ -1481,12 +1495,13 @@ pg_verify_mbstr(int encoding, const char *mbstr, int len, bool noError)
|
||||
{
|
||||
if (*mbstr != '\0')
|
||||
{
|
||||
mb_len++;
|
||||
mbstr++;
|
||||
len--;
|
||||
continue;
|
||||
}
|
||||
if (noError)
|
||||
return false;
|
||||
return -1;
|
||||
report_invalid_encoding(encoding, mbstr, len);
|
||||
}
|
||||
|
||||
@@ -1495,14 +1510,15 @@ pg_verify_mbstr(int encoding, const char *mbstr, int len, bool noError)
|
||||
if (l < 0)
|
||||
{
|
||||
if (noError)
|
||||
return false;
|
||||
return -1;
|
||||
report_invalid_encoding(encoding, mbstr, len);
|
||||
}
|
||||
|
||||
mbstr += l;
|
||||
len -= l;
|
||||
mb_len++;
|
||||
}
|
||||
return true;
|
||||
return mb_len;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user