Details
-
Bug
-
Status: Open (View Workflow)
-
Minor
-
Resolution: Unresolved
-
10.9(EOL), 10.10(EOL)
-
None
-
`mariadb:10.9` and `mariadb:10.10` docker images
Description
There is some inconsistent behavior for the `result`/`length` behavior in string-based user-defined functions.
This isn't exactly documented in MariaDB, but from the MySQL docs:
MySQL passes a buffer to the xxx() function using the result parameter. This buffer is sufficiently long to hold 255 characters, which can be multibyte characters. The xxx() function can store the result in this buffer if it fits, in which case the return value should be a pointer to the buffer. If the function stores the result in a different buffer, it should return a pointer to that buffer.
MariaDB and MySQL have the same behavior: if a `cfg.max_length` is set in `xxx_init()` that is less than 255, then the `result` buffer will have a length of 766 when `xxx()` is called (I am unsure why 766 and not `cfg.max_length`).
However, this behavior differs when `xxx` is called within another function or in some different contexts, e.g. `yyy(xxx())`. For some reason, this pattern makes MariaDB pass a `length` of 0 to `xxx()`, rather than the expected `max_length` or 755.
I have a simple function `lookup6` that returns an ipv6 IP for a host if found. Example correct behavior: logs when running `select lookup6('0.0.0.0')`:
2022-12-11T23:39:13.7807854Z 2022-12-11 23:39:13+00:00 [Debug] UDF: entering process for `udf_examples::lookup::Lookup6`
|
2022-12-11T23:39:13.7808068Z 2022-12-11 23:39:13+00:00 [Debug] UDF: Data receive state at process:
|
2022-12-11T23:39:13.7808209Z [udf/src/wrapper/debug.rs:157] &*initid = UDF_INIT {
|
2022-12-11T23:39:13.7808298Z maybe_null: true,
|
// NOTE: max_length
|
...
|
2022-12-11T23:39:13.7808810Z }
|
...
|
2022-12-11T23:39:13.7810121Z [udf/src/wrapper/debug.rs:159] result = 0x00007f2538bb36c0
|
// NOTE: got a buffer of length 766
|
2022-12-11T23:39:13.7810254Z [udf/src/wrapper/debug.rs:160] &*length = 766
|
2022-12-11T23:39:13.7810375Z [udf/src/wrapper/debug.rs:161] &*is_null = 0
|
2022-12-11T23:39:13.7810494Z [udf/src/wrapper/debug.rs:162] &*error = 0
|
Example of the problem: logs when running `set @testval = (select lookup6('0.0.0.0'))`
2022-12-11T23:39:13.7820777Z 2022-12-11 23:39:13+00:00 [Debug] UDF: entering process for `udf_examples::lookup::Lookup6`
|
2022-12-11T23:39:13.7820987Z 2022-12-11 23:39:13+00:00 [Debug] UDF: Data receive state at process:
|
// NOTE: max_length
|
2022-12-11T23:39:13.7821126Z [udf/src/wrapper/debug.rs:157] &*initid = UDF_INIT {
|
2022-12-11T23:39:13.7821216Z maybe_null: true,
|
2022-12-11T23:39:13.7821380Z max_length: 39,
|
...
|
2022-12-11T23:39:13.7821731Z }
|
...
|
2022-12-11T23:39:13.7822860Z [udf/src/wrapper/debug.rs:159] result = 0x00007f24f807c618
|
// NOTE: length 0
|
2022-12-11T23:39:13.7822984Z [udf/src/wrapper/debug.rs:160] &*length = 0
|
2022-12-11T23:39:13.7823110Z [udf/src/wrapper/debug.rs:161] &*is_null = 0
|
2022-12-11T23:39:13.7823231Z [udf/src/wrapper/debug.rs:162] &*error = 0
|
2022-12-11T23:39:13.7823570Z 2022-12-11 23:39:13+00:00 [Debug] UDF: 0x1 0 bytes server->udf control transfer (udf_examples::lookup::Lookup6)
|
2022-12-11T23:39:13.7824003Z 2022-12-11 23:39:13+00:00 [Critical] UDF: output overflow, returning NULL. Buffer size: 0, data length: 14 at `udf_examples::lookup::Lookup6::process`
|
2022-12-11T23:39:13.7824259Z 2022-12-11 23:39:13+00:00 [Critical] UDF: contact your UDF vendor as this is a serious bug
|
2022-12-11T23:39:13.7824517Z 2022-12-11 23:39:13+00:00 [Critical] UDF: run with `RUST_LIB_BACKTRACE=1` for a full backtrace
|
2022-12-11T23:39:13.7824601Z Backtrace [
|
2022-12-11T23:39:13.7824754Z { fn: "udf::wrapper::helpers::buf_result_callback" },
|
2022-12-11T23:39:13.7824844Z { fn: "lookup6" },
|
2022-12-11T23:39:13.7824987Z { fn: "_ZN11udf_handler7val_strEP6StringS1_" },
|
2022-12-11T23:39:13.7825173Z { fn: "_ZN17Item_func_udf_str7val_strEP6String" },
|
2022-12-11T23:39:13.7825309Z { fn: "_ZN22Item_func_set_user_var5checkEb" },
|
...
|
Source that catches this error: https://github.com/pluots/sql-udf/tree/4e4ded2f1f24bdb1052fe45262f73e87d5f1e2bb