Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b631d01

Browse files
committed
Fix pl/tcl's handling of errors from Tcl_ListObjGetElements().
In a procedure or function returning tuple, we use that function to parse the Tcl script's result, which is supposed to be a Tcl list. If it isn't, you get an error. Commit 26abb50 incautiously supposed that we could use throw_tcl_error() to report such an error. That doesn't actually work, because low-level functions like Tcl_ListObjGetElements() don't fill Tcl's errorInfo variable. The result is either a null-pointer-dereference crash or emission of misleading context information describing the previous Tcl error. Back off to just reporting the interpreter's result string, and improve throw_tcl_error()'s comment to explain when to use it. Also, although the similar code in pltcl_trigger_handler() avoided this mistake, it was using a fairly confusing wording of the error message. Improve that while we're here. Per report from A. Kozhemyakin. Back-patch to all supported branches. Erik Wienhold and Tom Lane Discussion: https://postgr.es/m/6a2a1c40-2b2c-4a33-8b72-243c0766fcda@postgrespro.ru
1 parent cd2624f commit b631d01

File tree

3 files changed

+28
-2
lines changed

3 files changed

+28
-2
lines changed

src/pl/tcl/expected/pltcl_call.out

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ END
6666
$$;
6767
NOTICE: a: 10
6868
NOTICE: _a: 10, _b: 20
69+
-- syntax error in result tuple
70+
CREATE PROCEDURE test_proc10(INOUT a text)
71+
LANGUAGE pltcl
72+
AS $$
73+
return [list a {$a + $a}])
74+
$$;
75+
CALL test_proc10('abc');
76+
ERROR: could not parse function return value: list element in braces followed by ")" instead of space
6977
DROP PROCEDURE test_proc1;
7078
DROP PROCEDURE test_proc2;
7179
DROP PROCEDURE test_proc3;

src/pl/tcl/pltcl.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,7 +1026,10 @@ pltcl_func_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state,
10261026
/* Convert function result to tuple */
10271027
resultObj = Tcl_GetObjResult(interp);
10281028
if (Tcl_ListObjGetElements(interp, resultObj, &resultObjc, &resultObjv) == TCL_ERROR)
1029-
throw_tcl_error(interp, prodesc->user_proname);
1029+
ereport(ERROR,
1030+
(errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
1031+
errmsg("could not parse function return value: %s",
1032+
utf_u2e(Tcl_GetStringResult(interp)))));
10301033

10311034
tup = pltcl_build_tuple_result(interp, resultObjv, resultObjc,
10321035
call_state);
@@ -1292,7 +1295,7 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state,
12921295
&result_Objc, &result_Objv) != TCL_OK)
12931296
ereport(ERROR,
12941297
(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
1295-
errmsg("could not split return value from trigger: %s",
1298+
errmsg("could not parse trigger return value: %s",
12961299
utf_u2e(Tcl_GetStringResult(interp)))));
12971300

12981301
/* Convert function result to tuple */
@@ -1355,6 +1358,10 @@ pltcl_event_trigger_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state,
13551358

13561359
/**********************************************************************
13571360
* throw_tcl_error - ereport an error returned from the Tcl interpreter
1361+
*
1362+
* Caution: use this only to report errors returned by Tcl_EvalObjEx() or
1363+
* other variants of Tcl_Eval(). Other functions may not fill "errorInfo",
1364+
* so it could be unset or even contain details from some previous error.
13581365
**********************************************************************/
13591366
static void
13601367
throw_tcl_error(Tcl_Interp *interp, const char *proname)

src/pl/tcl/sql/pltcl_call.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,17 @@ END
7171
$$;
7272

7373

74+
-- syntax error in result tuple
75+
76+
CREATE PROCEDURE test_proc10(INOUT a text)
77+
LANGUAGE pltcl
78+
AS $$
79+
return [list a {$a + $a}])
80+
$$;
81+
82+
CALL test_proc10('abc');
83+
84+
7485
DROP PROCEDURE test_proc1;
7586
DROP PROCEDURE test_proc2;
7687
DROP PROCEDURE test_proc3;

0 commit comments

Comments
 (0)