zsh-workers
 help / color / mirror / code / Atom feed
From: Bart Schaefer <schaefer@brasslantern.com>
To: Zsh hackers list <zsh-workers@zsh.org>
Subject: [PATCH] math recursion and array overflow
Date: Fri, 19 Jan 2024 21:51:46 -0800	[thread overview]
Message-ID: <CAH+w=7Yoh=rigAAZb7W_3b6ODsw9hNec5ofk1p7jvPYSW2HeLg@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 790 bytes --]

Math operations normally abort if recursion gets deeper than MAX_MLEVEL (256).

However, if the recursion is happening in an array subscript, it can
rewind and try again until eventually we try to calculate the length
of an empty array expansion, and kaboom.

This happens because parse_subscript() clears the error flag while
using the lexer, so instead of stopping at the recursion limit we just
try again on the next subscript until something goes wrong.

The easiest way to reproduce is to use a nameref:

n=(1)
typeset -n i='n[++i]'
print $i

The following fixes it by aborting math operators upon operand error,
but there might be other more elaborate ways to set it off.  I tried
some combinations using user-defined math functions but didn't find a
failing recursive call strategy.

[-- Attachment #2: math-array-overflow.txt --]
[-- Type: text/plain, Size: 647 bytes --]

diff --git a/Src/math.c b/Src/math.c
index a060181ed..50b69d6a1 100644
--- a/Src/math.c
+++ b/Src/math.c
@@ -352,6 +352,8 @@ getmathparam(struct mathvalue *mptr)
 	    }
 	    return zero_mnumber;
 	}
+	if (errflag)
+	    return zero_mnumber;
     }
     result = getnumvalue(mptr->pval);
     if (isset(FORCEFLOAT) && result.type == MN_INTEGER) {
@@ -1367,8 +1369,11 @@ op(int what)
     }
 
     spval = &stack[sp].val;
-    if (stack[sp].val.type == MN_UNSET)
+    if (stack[sp].val.type == MN_UNSET) {
 	*spval = getmathparam(stack + sp);
+	if (errflag)
+	    return;
+    }
     switch (what) {
     case NOT:
 	if (spval->type & MN_FLOAT) {

                 reply	other threads:[~2024-01-20  5:52 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAH+w=7Yoh=rigAAZb7W_3b6ODsw9hNec5ofk1p7jvPYSW2HeLg@mail.gmail.com' \
    --to=schaefer@brasslantern.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).