summaryrefslogtreecommitdiff
path: root/mg.c
diff options
context:
space:
mode:
authorTony Cook <tony@develop-help.com>2023-01-23 15:28:12 +1100
committerTony Cook <tony@develop-help.com>2023-01-25 09:26:27 +1100
commitaf62106ad344b13fde54d2c0d5e7e0d0bab96054 (patch)
treec2f835b80175fdfd0e3ff533e6271dda9a1aeac8 /mg.c
parentfa1fe46855cd623ff0f787f3025c3c3f14cd57b4 (diff)
downloadperl-af62106ad344b13fde54d2c0d5e7e0d0bab96054.tar.gz
check the IO object exists when writing to IO magic variables
pp_select() ensures that the GV in PL_defoutgv has an IO object when it the default output is set, but can't prevent that GV being cleared afterwards, resulting in a seg fault when the variable is written. To prevent this, check PL_defoutgv has an IO object before trying to write to it. Fixes #20733
Diffstat (limited to 'mg.c')
-rw-r--r--mg.c52
1 files changed, 41 insertions, 11 deletions
diff --git a/mg.c b/mg.c
index 5366f5767a..530cb9f05b 100644
--- a/mg.c
+++ b/mg.c
@@ -3072,25 +3072,55 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
IoLINES(GvIOp(PL_last_in_gv)) = SvIV(sv);
break;
case '^':
- Safefree(IoTOP_NAME(GvIOp(PL_defoutgv)));
- IoTOP_NAME(GvIOp(PL_defoutgv)) = savesvpv(sv);
- IoTOP_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv, GV_ADD, SVt_PVIO);
+ {
+ IO * const io = GvIO(PL_defoutgv);
+ if (!io)
+ break;
+
+ Safefree(IoTOP_NAME(io));
+ IoTOP_NAME(io) = savesvpv(sv);
+ IoTOP_GV(io) = gv_fetchsv(sv, GV_ADD, SVt_PVIO);
+ }
break;
case '~':
- Safefree(IoFMT_NAME(GvIOp(PL_defoutgv)));
- IoFMT_NAME(GvIOp(PL_defoutgv)) = savesvpv(sv);
- IoFMT_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv, GV_ADD, SVt_PVIO);
+ {
+ IO * const io = GvIO(PL_defoutgv);
+ if (!io)
+ break;
+
+ Safefree(IoFMT_NAME(io));
+ IoFMT_NAME(io) = savesvpv(sv);
+ IoFMT_GV(io) = gv_fetchsv(sv, GV_ADD, SVt_PVIO);
+ }
break;
case '=':
- IoPAGE_LEN(GvIOp(PL_defoutgv)) = (SvIV(sv));
+ {
+ IO * const io = GvIO(PL_defoutgv);
+ if (!io)
+ break;
+
+ IoPAGE_LEN(io) = (SvIV(sv));
+ }
break;
case '-':
- IoLINES_LEFT(GvIOp(PL_defoutgv)) = (SvIV(sv));
- if (IoLINES_LEFT(GvIOp(PL_defoutgv)) < 0L)
- IoLINES_LEFT(GvIOp(PL_defoutgv)) = 0L;
+ {
+ IO * const io = GvIO(PL_defoutgv);
+ if (!io)
+ break;
+
+ IoLINES_LEFT(io) = (SvIV(sv));
+ if (IoLINES_LEFT(io) < 0L)
+ IoLINES_LEFT(io) = 0L;
+ }
break;
case '%':
- IoPAGE(GvIOp(PL_defoutgv)) = (SvIV(sv));
+ {
+ IO * const io = GvIO(PL_defoutgv);
+ if (!io)
+ break;
+
+ IoPAGE(io) = (SvIV(sv));
+ }
break;
case '|':
{