Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4eec2e0

Browse files
committed
Be more careful to avoid including system headers after perl.h
Commit 121d2d3 included simd.h into pg_wchar.h. This caused a problem on Windows, since Perl has "#define free" (referring to globals), which breaks the Windows' header. To fix, move the static inline function definitions from plperl_helpers.h, into plperl.h, where we already document the necessary inclusion order. Since those functions were the only reason for the existence of plperl_helpers.h, remove it. First reported by Justin Pryzby Diagnosis and review by Andres Freund, patch by myself per suggestion from Tom Lane Discussion: https://www.postgresql.org/message-id/20220826115546.GE2342%40telsasoft.com
1 parent 52144b6 commit 4eec2e0

File tree

8 files changed

+171
-180
lines changed

8 files changed

+171
-180
lines changed

contrib/hstore_plperl/hstore_plperl.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#include "fmgr.h"
44
#include "hstore/hstore.h"
55
#include "plperl.h"
6-
#include "plperl_helpers.h"
76

87
PG_MODULE_MAGIC;
98

contrib/jsonb_plperl/jsonb_plperl.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
#include "fmgr.h"
66
#include "plperl.h"
7-
#include "plperl_helpers.h"
87
#include "utils/fmgrprotos.h"
98
#include "utils/jsonb.h"
109

src/pl/plperl/GNUmakefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ XSUBPPDIR = $(shell $(PERL) -e 'use List::Util qw(first); print first { -r "$$_/
7272

7373
include $(top_srcdir)/src/Makefile.shlib
7474

75-
plperl.o: perlchunks.h plperl_opmask.h plperl_helpers.h
75+
plperl.o: perlchunks.h plperl_opmask.h
7676

7777
plperl_opmask.h: plperl_opmask.pl
7878
@if [ x"$(perl_privlibexp)" = x"" ]; then echo "configure switch --with-perl was not specified."; exit 1; fi
@@ -103,7 +103,7 @@ uninstall: uninstall-lib uninstall-data
103103

104104
install-data: installdirs
105105
$(INSTALL_DATA) $(addprefix $(srcdir)/, $(DATA)) '$(DESTDIR)$(datadir)/extension/'
106-
$(INSTALL_DATA) $(srcdir)/plperl.h $(srcdir)/ppport.h $(srcdir)/plperl_helpers.h '$(DESTDIR)$(includedir_server)'
106+
$(INSTALL_DATA) $(srcdir)/plperl.h $(srcdir)/ppport.h '$(DESTDIR)$(includedir_server)'
107107

108108
uninstall-data:
109109
rm -f $(addprefix '$(DESTDIR)$(datadir)/extension'/, $(notdir $(DATA)))

src/pl/plperl/SPI.xs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
/* perl stuff */
1414
#define PG_NEED_PERL_XSUB_H
1515
#include "plperl.h"
16-
#include "plperl_helpers.h"
1716

1817

1918
MODULE = PostgreSQL::InServer::SPI PREFIX = spi_

src/pl/plperl/Util.xs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
/* perl stuff */
2121
#define PG_NEED_PERL_XSUB_H
2222
#include "plperl.h"
23-
#include "plperl_helpers.h"
2423

2524

2625
static text *

src/pl/plperl/plperl.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
#include "commands/trigger.h"
2424
#include "executor/spi.h"
2525
#include "funcapi.h"
26-
#include "mb/pg_wchar.h"
2726
#include "miscadmin.h"
2827
#include "nodes/makefuncs.h"
2928
#include "parser/parse_type.h"
@@ -47,7 +46,6 @@
4746
/* string literal macros defining chunks of perl code */
4847
#include "perlchunks.h"
4948
#include "plperl.h"
50-
#include "plperl_helpers.h"
5149
/* defines PLPERL_SET_OPMASK */
5250
#include "plperl_opmask.h"
5351

src/pl/plperl/plperl.h

Lines changed: 169 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
* plperl.h
44
* Common include file for PL/Perl files
55
*
6-
* This should be included _AFTER_ postgres.h and system include files
6+
* This should be included _AFTER_ postgres.h and system include files, as
7+
* well as headers that could in turn include system headers.
78
*
89
* Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
910
* Portions Copyright (c) 1995, Regents of the University of California
@@ -14,6 +15,9 @@
1415
#ifndef PL_PERL_H
1516
#define PL_PERL_H
1617

18+
/* defines free() by way of system headers, so must be included before perl.h */
19+
#include "mb/pg_wchar.h"
20+
1721
/* stop perl headers from hijacking stdio and other stuff on Windows */
1822
#ifdef WIN32
1923
#define WIN32IO_IS_STDIO
@@ -213,4 +217,168 @@ void plperl_spi_rollback(void);
213217
char *plperl_sv_to_literal(SV *, char *);
214218
void plperl_util_elog(int level, SV *msg);
215219

220+
221+
/* helper functions */
222+
223+
/*
224+
* convert from utf8 to database encoding
225+
*
226+
* Returns a palloc'ed copy of the original string
227+
*/
228+
static inline char *
229+
utf_u2e(char *utf8_str, size_t len)
230+
{
231+
char *ret;
232+
233+
ret = pg_any_to_server(utf8_str, len, PG_UTF8);
234+
235+
/* ensure we have a copy even if no conversion happened */
236+
if (ret == utf8_str)
237+
ret = pstrdup(ret);
238+
239+
return ret;
240+
}
241+
242+
/*
243+
* convert from database encoding to utf8
244+
*
245+
* Returns a palloc'ed copy of the original string
246+
*/
247+
static inline char *
248+
utf_e2u(const char *str)
249+
{
250+
char *ret;
251+
252+
ret = pg_server_to_any(str, strlen(str), PG_UTF8);
253+
254+
/* ensure we have a copy even if no conversion happened */
255+
if (ret == str)
256+
ret = pstrdup(ret);
257+
258+
return ret;
259+
}
260+
261+
/*
262+
* Convert an SV to a char * in the current database encoding
263+
*
264+
* Returns a palloc'ed copy of the original string
265+
*/
266+
static inline char *
267+
sv2cstr(SV *sv)
268+
{
269+
dTHX;
270+
char *val,
271+
*res;
272+
STRLEN len;
273+
274+
/*
275+
* get a utf8 encoded char * out of perl. *note* it may not be valid utf8!
276+
*/
277+
278+
/*
279+
* SvPVutf8() croaks nastily on certain things, like typeglobs and
280+
* readonly objects such as $^V. That's a perl bug - it's not supposed to
281+
* happen. To avoid crashing the backend, we make a copy of the sv before
282+
* passing it to SvPVutf8(). The copy is garbage collected when we're done
283+
* with it.
284+
*/
285+
if (SvREADONLY(sv) ||
286+
isGV_with_GP(sv) ||
287+
(SvTYPE(sv) > SVt_PVLV && SvTYPE(sv) != SVt_PVFM))
288+
sv = newSVsv(sv);
289+
else
290+
{
291+
/*
292+
* increase the reference count so we can just SvREFCNT_dec() it when
293+
* we are done
294+
*/
295+
SvREFCNT_inc_simple_void(sv);
296+
}
297+
298+
/*
299+
* Request the string from Perl, in UTF-8 encoding; but if we're in a
300+
* SQL_ASCII database, just request the byte soup without trying to make
301+
* it UTF8, because that might fail.
302+
*/
303+
if (GetDatabaseEncoding() == PG_SQL_ASCII)
304+
val = SvPV(sv, len);
305+
else
306+
val = SvPVutf8(sv, len);
307+
308+
/*
309+
* Now convert to database encoding. We use perl's length in the event we
310+
* had an embedded null byte to ensure we error out properly.
311+
*/
312+
res = utf_u2e(val, len);
313+
314+
/* safe now to garbage collect the new SV */
315+
SvREFCNT_dec(sv);
316+
317+
return res;
318+
}
319+
320+
/*
321+
* Create a new SV from a string assumed to be in the current database's
322+
* encoding.
323+
*/
324+
static inline SV *
325+
cstr2sv(const char *str)
326+
{
327+
dTHX;
328+
SV *sv;
329+
char *utf8_str;
330+
331+
/* no conversion when SQL_ASCII */
332+
if (GetDatabaseEncoding() == PG_SQL_ASCII)
333+
return newSVpv(str, 0);
334+
335+
utf8_str = utf_e2u(str);
336+
337+
sv = newSVpv(utf8_str, 0);
338+
SvUTF8_on(sv);
339+
pfree(utf8_str);
340+
341+
return sv;
342+
}
343+
344+
/*
345+
* croak() with specified message, which is given in the database encoding.
346+
*
347+
* Ideally we'd just write croak("%s", str), but plain croak() does not play
348+
* nice with non-ASCII data. In modern Perl versions we can call cstr2sv()
349+
* and pass the result to croak_sv(); in versions that don't have croak_sv(),
350+
* we have to work harder.
351+
*/
352+
static inline void
353+
croak_cstr(const char *str)
354+
{
355+
dTHX;
356+
357+
#ifdef croak_sv
358+
/* Use sv_2mortal() to be sure the transient SV gets freed */
359+
croak_sv(sv_2mortal(cstr2sv(str)));
360+
#else
361+
362+
/*
363+
* The older way to do this is to assign a UTF8-marked value to ERRSV and
364+
* then call croak(NULL). But if we leave it to croak() to append the
365+
* error location, it does so too late (only after popping the stack) in
366+
* some Perl versions. Hence, use mess() to create an SV with the error
367+
* location info already appended.
368+
*/
369+
SV *errsv = get_sv("@", GV_ADD);
370+
char *utf8_str = utf_e2u(str);
371+
SV *ssv;
372+
373+
ssv = mess("%s", utf8_str);
374+
SvUTF8_on(ssv);
375+
376+
pfree(utf8_str);
377+
378+
sv_setsv(errsv, ssv);
379+
380+
croak(NULL);
381+
#endif /* croak_sv */
382+
}
383+
216384
#endif /* PL_PERL_H */

0 commit comments

Comments
 (0)