fixes #4912
---
main/putty/APKBUILD | 14 ++-
main/putty/CVE-2015-5309.patch | 250 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 259 insertions(+), 5 deletions(-)
create mode 100644 main/putty/CVE-2015-5309.patch
diff --git a/main/putty/APKBUILD b/main/putty/APKBUILD
index 23acdd8..ae8b173 100644
--- a/main/putty/APKBUILD
+++ b/main/putty/APKBUILD
@@ -11,7 +11,9 @@ depends_dev=
makedepends="$depends_dev"
install=""
subpackages="$pkgname-doc"
-source="http://the.earth.li/~sgtatham/putty/latest/putty-$pkgver.tar.gz"
+source="http://the.earth.li/~sgtatham/putty/$pkgver/putty-$pkgver.tar.gz
+ CVE-2015-5309.patch
+ "
_builddir="$srcdir"/putty-$pkgver
prepare() {
@@ -38,7 +40,9 @@ package() {
cd "$_builddir"
make DESTDIR="$pkgdir" install || return 1
}
-
-md5sums="75ff711e8b7cc9e0073bc511e1c1c14a putty-0.64.tar.gz"
-sha256sums="2a46c97a184144e3ec2392aca9acc64d062317a3a38b9a5f623a147eda5f3821 putty-0.64.tar.gz"
-sha512sums="ba4d4086b8edcb6388924bf3d9b018841be36a9dbf298271c9d2ed063aae9854093e9ff6808bd1f65669d78369548639eb3c95fdec5e3f0daee4b1c7bb603051 putty-0.64.tar.gz"
+md5sums="75ff711e8b7cc9e0073bc511e1c1c14a putty-0.64.tar.gz
+dfdc6d6f52e33811ce72f6f1614f71e8 CVE-2015-5309.patch"
+sha256sums="2a46c97a184144e3ec2392aca9acc64d062317a3a38b9a5f623a147eda5f3821 putty-0.64.tar.gz
+b49a26d0ad2578acbe7e106fad010d333ca09ce5272774e4e2ce3805f37f9780 CVE-2015-5309.patch"
+sha512sums="ba4d4086b8edcb6388924bf3d9b018841be36a9dbf298271c9d2ed063aae9854093e9ff6808bd1f65669d78369548639eb3c95fdec5e3f0daee4b1c7bb603051 putty-0.64.tar.gz
+692f06ed53b8d4a6b3d041ece83d0d36601d0fcaa0b7a207b52ed57be0dea108681785466f65599ab85f4b8d164b0849c7d0b3f0f54999517390f06547163e5a CVE-2015-5309.patch"
diff --git a/main/putty/CVE-2015-5309.patch b/main/putty/CVE-2015-5309.patch
new file mode 100644
index 0000000..2225b2c
--- /dev/null
+++ b/main/putty/CVE-2015-5309.patch
@@ -0,0 +1,250 @@
+From 6056396f77cafc7e40da4d09f1d6212408dcb065 Mon Sep 17 00:00:00 2001
+From: Ben Harris <bjh21@bjh21.me.uk>
+Date: Wed, 7 Oct 2015 23:54:39 +0100
+Subject: [PATCH] More robust control sequence parameter handling.
+
+Parameters are now accumulated in unsigned integers and carefully checked
+for overflow (which is turned into saturation). Things that consume them
+now have explicit range checks (again, saturating) to ensure that their
+inputs are sane. This should make it much harder to cause overflow by
+supplying ludicrously large numbers.
+
+Fixes two bugs found with the help of afl-fuzz. One of them may be
+exploitable and is CVE-2015-5309.
+---
+ terminal.c | 49 +++++++++++++++++++++++++++++++++++++++++++------
+ terminal.h | 2 +-
+ 2 files changed, 44 insertions(+), 7 deletions(-)
+
+diff --git a/terminal.c b/terminal.c
+index d8d0ea0..c7e2647 100644
+--- a/terminal.c
++++ b/terminal.c
+@@ -5,6 +5,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <ctype.h>
++#include <limits.h>
+
+ #include <time.h>
+ #include <assert.h>
+@@ -3493,8 +3494,15 @@ static void term_out(Terminal *term)
+ if (term->esc_nargs <= ARGS_MAX) {
+ if (term->esc_args[term->esc_nargs - 1] == ARG_DEFAULT)
+ term->esc_args[term->esc_nargs - 1] = 0;
+- term->esc_args[term->esc_nargs - 1] =
+- 10 * term->esc_args[term->esc_nargs - 1] + c - '0';
++ if (term->esc_args[term->esc_nargs - 1] <=
++ UINT_MAX / 10 &&
++ term->esc_args[term->esc_nargs - 1] * 10 <=
++ UINT_MAX - c - '0')
++ term->esc_args[term->esc_nargs - 1] =
++ 10 * term->esc_args[term->esc_nargs - 1] +
++ c - '0';
++ else
++ term->esc_args[term->esc_nargs - 1] = UINT_MAX;
+ }
+ term->termstate = SEEN_CSI;
+ } else if (c == ';') {
+@@ -3510,8 +3518,10 @@ static void term_out(Terminal *term)
+ term->esc_query = c;
+ term->termstate = SEEN_CSI;
+ } else
++#define CLAMP(arg, lim) ((arg) = ((arg) > (lim)) ? (lim) : (arg))
+ switch (ANSI(c, term->esc_query)) {
+ case 'A': /* CUU: move up N lines */
++ CLAMP(term->esc_args[0], term->rows);
+ move(term, term->curs.x,
+ term->curs.y - def(term->esc_args[0], 1), 1);
+ seen_disp_event(term);
+@@ -3520,6 +3530,7 @@ static void term_out(Terminal *term)
+ compatibility(ANSI);
+ /* FALLTHROUGH */
+ case 'B': /* CUD: Cursor down */
++ CLAMP(term->esc_args[0], term->rows);
+ move(term, term->curs.x,
+ term->curs.y + def(term->esc_args[0], 1), 1);
+ seen_disp_event(term);
+@@ -3535,23 +3546,27 @@ static void term_out(Terminal *term)
+ compatibility(ANSI);
+ /* FALLTHROUGH */
+ case 'C': /* CUF: Cursor right */
++ CLAMP(term->esc_args[0], term->cols);
+ move(term, term->curs.x + def(term->esc_args[0], 1),
+ term->curs.y, 1);
+ seen_disp_event(term);
+ break;
+ case 'D': /* CUB: move left N cols */
++ CLAMP(term->esc_args[0], term->cols);
+ move(term, term->curs.x - def(term->esc_args[0], 1),
+ term->curs.y, 1);
+ seen_disp_event(term);
+ break;
+ case 'E': /* CNL: move down N lines and CR */
+ compatibility(ANSI);
++ CLAMP(term->esc_args[0], term->rows);
+ move(term, 0,
+ term->curs.y + def(term->esc_args[0], 1), 1);
+ seen_disp_event(term);
+ break;
+ case 'F': /* CPL: move up N lines and CR */
+ compatibility(ANSI);
++ CLAMP(term->esc_args[0], term->rows);
+ move(term, 0,
+ term->curs.y - def(term->esc_args[0], 1), 1);
+ seen_disp_event(term);
+@@ -3559,12 +3574,14 @@ static void term_out(Terminal *term)
+ case 'G': /* CHA */
+ case '`': /* HPA: set horizontal posn */
+ compatibility(ANSI);
++ CLAMP(term->esc_args[0], term->cols);
+ move(term, def(term->esc_args[0], 1) - 1,
+ term->curs.y, 0);
+ seen_disp_event(term);
+ break;
+ case 'd': /* VPA: set vertical posn */
+ compatibility(ANSI);
++ CLAMP(term->esc_args[0], term->rows);
+ move(term, term->curs.x,
+ ((term->dec_om ? term->marg_t : 0) +
+ def(term->esc_args[0], 1) - 1),
+@@ -3575,6 +3592,8 @@ static void term_out(Terminal *term)
+ case 'f': /* HVP: set horz and vert posns at once */
+ if (term->esc_nargs < 2)
+ term->esc_args[1] = ARG_DEFAULT;
++ CLAMP(term->esc_args[0], term->rows);
++ CLAMP(term->esc_args[1], term->cols);
+ move(term, def(term->esc_args[1], 1) - 1,
+ ((term->dec_om ? term->marg_t : 0) +
+ def(term->esc_args[0], 1) - 1),
+@@ -3610,6 +3629,7 @@ static void term_out(Terminal *term)
+ break;
+ case 'L': /* IL: insert lines */
+ compatibility(VT102);
++ CLAMP(term->esc_args[0], term->rows);
+ if (term->curs.y <= term->marg_b)
+ scroll(term, term->curs.y, term->marg_b,
+ -def(term->esc_args[0], 1), FALSE);
+@@ -3617,6 +3637,7 @@ static void term_out(Terminal *term)
+ break;
+ case 'M': /* DL: delete lines */
+ compatibility(VT102);
++ CLAMP(term->esc_args[0], term->rows);
+ if (term->curs.y <= term->marg_b)
+ scroll(term, term->curs.y, term->marg_b,
+ def(term->esc_args[0], 1),
+@@ -3626,11 +3647,13 @@ static void term_out(Terminal *term)
+ case '@': /* ICH: insert chars */
+ /* XXX VTTEST says this is vt220, vt510 manual says vt102 */
+ compatibility(VT102);
++ CLAMP(term->esc_args[0], term->cols);
+ insch(term, def(term->esc_args[0], 1));
+ seen_disp_event(term);
+ break;
+ case 'P': /* DCH: delete chars */
+ compatibility(VT102);
++ CLAMP(term->esc_args[0], term->cols);
+ insch(term, -def(term->esc_args[0], 1));
+ seen_disp_event(term);
+ break;
+@@ -3708,6 +3731,8 @@ static void term_out(Terminal *term)
+ compatibility(VT100);
+ if (term->esc_nargs <= 2) {
+ int top, bot;
++ CLAMP(term->esc_args[0], term->rows);
++ CLAMP(term->esc_args[1], term->rows);
+ top = def(term->esc_args[0], 1) - 1;
+ bot = (term->esc_nargs <= 1
+ || term->esc_args[1] == 0 ?
+@@ -4062,6 +4087,7 @@ static void term_out(Terminal *term)
+ }
+ break;
+ case 'S': /* SU: Scroll up */
++ CLAMP(term->esc_args[0], term->rows);
+ compatibility(SCOANSI);
+ scroll(term, term->marg_t, term->marg_b,
+ def(term->esc_args[0], 1), TRUE);
+@@ -4069,6 +4095,7 @@ static void term_out(Terminal *term)
+ seen_disp_event(term);
+ break;
+ case 'T': /* SD: Scroll down */
++ CLAMP(term->esc_args[0], term->rows);
+ compatibility(SCOANSI);
+ scroll(term, term->marg_t, term->marg_b,
+ -def(term->esc_args[0], 1), TRUE);
+@@ -4111,6 +4138,7 @@ static void term_out(Terminal *term)
+ /* XXX VTTEST says this is vt220, vt510 manual
+ * says vt100 */
+ compatibility(ANSIMIN);
++ CLAMP(term->esc_args[0], term->cols);
+ {
+ int n = def(term->esc_args[0], 1);
+ pos cursplus;
+@@ -4144,6 +4172,7 @@ static void term_out(Terminal *term)
+ break;
+ case 'Z': /* CBT */
+ compatibility(OTHER);
++ CLAMP(term->esc_args[0], term->cols);
+ {
+ int i = def(term->esc_args[0], 1);
+ pos old_curs = term->curs;
+@@ -4204,7 +4233,7 @@ static void term_out(Terminal *term)
+ break;
+ case ANSI('F', '='): /* set normal foreground */
+ compatibility(SCOANSI);
+- if (term->esc_args[0] >= 0 && term->esc_args[0] < 16) {
++ if (term->esc_args[0] < 16) {
+ long colour =
+ (sco2ansicolour[term->esc_args[0] & 0x7] |
+ (term->esc_args[0] & 0x8)) <<
+@@ -4218,7 +4247,7 @@ static void term_out(Terminal *term)
+ break;
+ case ANSI('G', '='): /* set normal background */
+ compatibility(SCOANSI);
+- if (term->esc_args[0] >= 0 && term->esc_args[0] < 16) {
++ if (term->esc_args[0] < 16) {
+ long colour =
+ (sco2ansicolour[term->esc_args[0] & 0x7] |
+ (term->esc_args[0] & 0x8)) <<
+@@ -4342,7 +4371,11 @@ static void term_out(Terminal *term)
+ case '7':
+ case '8':
+ case '9':
+- term->esc_args[0] = 10 * term->esc_args[0] + c - '0';
++ if (term->esc_args[0] <= UINT_MAX / 10 &&
++ term->esc_args[0] * 10 <= UINT_MAX - c - '0')
++ term->esc_args[0] = 10 * term->esc_args[0] + c - '0';
++ else
++ term->esc_args[0] = UINT_MAX;
+ break;
+ case 'L':
+ /*
+@@ -4424,7 +4457,11 @@ static void term_out(Terminal *term)
+ case '7':
+ case '8':
+ case '9':
+- term->esc_args[0] = 10 * term->esc_args[0] + c - '0';
++ if (term->esc_args[0] <= UINT_MAX / 10 &&
++ term->esc_args[0] * 10 <= UINT_MAX - c - '0')
++ term->esc_args[0] = 10 * term->esc_args[0] + c - '0';
++ else
++ term->esc_args[0] = UINT_MAX;
+ break;
+ default:
+ term->termstate = OSC_STRING;
+diff --git a/terminal.h b/terminal.h
+index 135ef45..01d5f57 100644
+--- a/terminal.h
++++ b/terminal.h
+@@ -172,7 +172,7 @@ struct terminal_tag {
+ #define ARGS_MAX 32 /* max # of esc sequence arguments */
+ #define ARG_DEFAULT 0 /* if an arg isn't specified */
+ #define def(a,d) ( (a) == ARG_DEFAULT ? (d) : (a) )
+- int esc_args[ARGS_MAX];
++ unsigned esc_args[ARGS_MAX];
+ int esc_nargs;
+ int esc_query;
+ #define ANSI(x,y) ((x)+((y)<<8))
+--
+1.7.10.4
+
--
2.6.2
---
Unsubscribe: alpine-aports+unsubscribe@lists.alpinelinux.org
Help: alpine-aports+help@lists.alpinelinux.org
---
This patch has been superseded by v2 because of missing pkgrel bump.
Christian Kampka <christian@kampka.net> schrieb am Mi., 2. Dez. 2015 um
19:30 Uhr:
> fixes #4912
> ---
> main/putty/APKBUILD | 14 ++-
> main/putty/CVE-2015-5309.patch | 250
> +++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 259 insertions(+), 5 deletions(-)
> create mode 100644 main/putty/CVE-2015-5309.patch
>
> diff --git a/main/putty/APKBUILD b/main/putty/APKBUILD
> index 23acdd8..ae8b173 100644
> --- a/main/putty/APKBUILD
> +++ b/main/putty/APKBUILD
> @@ -11,7 +11,9 @@ depends_dev=
> makedepends="$depends_dev"
> install=""
> subpackages="$pkgname-doc"
> -source="http://the.earth.li/~sgtatham/putty/latest/putty-$pkgver.tar.gz"
> +source="http://the.earth.li/~sgtatham/putty/$pkgver/putty-$pkgver.tar.gz
> + CVE-2015-5309.patch
> + "
>
> _builddir="$srcdir"/putty-$pkgver
> prepare() {
> @@ -38,7 +40,9 @@ package() {
> cd "$_builddir"
> make DESTDIR="$pkgdir" install || return 1
> }
> -
> -md5sums="75ff711e8b7cc9e0073bc511e1c1c14a putty-0.64.tar.gz"
> -sha256sums="2a46c97a184144e3ec2392aca9acc64d062317a3a38b9a5f623a147eda5f3821
> putty-0.64.tar.gz"
> -sha512sums="ba4d4086b8edcb6388924bf3d9b018841be36a9dbf298271c9d2ed063aae9854093e9ff6808bd1f65669d78369548639eb3c95fdec5e3f0daee4b1c7bb603051
> putty-0.64.tar.gz"
> +md5sums="75ff711e8b7cc9e0073bc511e1c1c14a putty-0.64.tar.gz
> +dfdc6d6f52e33811ce72f6f1614f71e8 CVE-2015-5309.patch"
> +sha256sums="2a46c97a184144e3ec2392aca9acc64d062317a3a38b9a5f623a147eda5f3821
> putty-0.64.tar.gz
> +b49a26d0ad2578acbe7e106fad010d333ca09ce5272774e4e2ce3805f37f9780
> CVE-2015-5309.patch"
> +sha512sums="ba4d4086b8edcb6388924bf3d9b018841be36a9dbf298271c9d2ed063aae9854093e9ff6808bd1f65669d78369548639eb3c95fdec5e3f0daee4b1c7bb603051
> putty-0.64.tar.gz
> +692f06ed53b8d4a6b3d041ece83d0d36601d0fcaa0b7a207b52ed57be0dea108681785466f65599ab85f4b8d164b0849c7d0b3f0f54999517390f06547163e5a
> CVE-2015-5309.patch"
> diff --git a/main/putty/CVE-2015-5309.patch
> b/main/putty/CVE-2015-5309.patch
> new file mode 100644
> index 0000000..2225b2c
> --- /dev/null
> +++ b/main/putty/CVE-2015-5309.patch
> @@ -0,0 +1,250 @@
> +From 6056396f77cafc7e40da4d09f1d6212408dcb065 Mon Sep 17 00:00:00 2001
> +From: Ben Harris <bjh21@bjh21.me.uk>
> +Date: Wed, 7 Oct 2015 23:54:39 +0100
> +Subject: [PATCH] More robust control sequence parameter handling.
> +
> +Parameters are now accumulated in unsigned integers and carefully checked
> +for overflow (which is turned into saturation). Things that consume them
> +now have explicit range checks (again, saturating) to ensure that their
> +inputs are sane. This should make it much harder to cause overflow by
> +supplying ludicrously large numbers.
> +
> +Fixes two bugs found with the help of afl-fuzz. One of them may be
> +exploitable and is CVE-2015-5309.
> +---
> + terminal.c | 49 +++++++++++++++++++++++++++++++++++++++++++------
> + terminal.h | 2 +-
> + 2 files changed, 44 insertions(+), 7 deletions(-)
> +
> +diff --git a/terminal.c b/terminal.c
> +index d8d0ea0..c7e2647 100644
> +--- a/terminal.c
> ++++ b/terminal.c
> +@@ -5,6 +5,7 @@
> + #include <stdio.h>
> + #include <stdlib.h>
> + #include <ctype.h>
> ++#include <limits.h>
> +
> + #include <time.h>
> + #include <assert.h>
> +@@ -3493,8 +3494,15 @@ static void term_out(Terminal *term)
> + if (term->esc_nargs <= ARGS_MAX) {
> + if (term->esc_args[term->esc_nargs - 1] ==
> ARG_DEFAULT)
> + term->esc_args[term->esc_nargs - 1] = 0;
> +- term->esc_args[term->esc_nargs - 1] =
> +- 10 * term->esc_args[term->esc_nargs - 1] + c -
> '0';
> ++ if (term->esc_args[term->esc_nargs - 1] <=
> ++ UINT_MAX / 10 &&
> ++ term->esc_args[term->esc_nargs - 1] * 10 <=
> ++ UINT_MAX - c - '0')
> ++ term->esc_args[term->esc_nargs - 1] =
> ++ 10 * term->esc_args[term->esc_nargs - 1] +
> ++ c - '0';
> ++ else
> ++ term->esc_args[term->esc_nargs - 1] = UINT_MAX;
> + }
> + term->termstate = SEEN_CSI;
> + } else if (c == ';') {
> +@@ -3510,8 +3518,10 @@ static void term_out(Terminal *term)
> + term->esc_query = c;
> + term->termstate = SEEN_CSI;
> + } else
> ++#define CLAMP(arg, lim) ((arg) = ((arg) > (lim)) ? (lim) : (arg))
> + switch (ANSI(c, term->esc_query)) {
> + case 'A': /* CUU: move up N lines */
> ++ CLAMP(term->esc_args[0], term->rows);
> + move(term, term->curs.x,
> + term->curs.y - def(term->esc_args[0], 1), 1);
> + seen_disp_event(term);
> +@@ -3520,6 +3530,7 @@ static void term_out(Terminal *term)
> + compatibility(ANSI);
> + /* FALLTHROUGH */
> + case 'B': /* CUD: Cursor down */
> ++ CLAMP(term->esc_args[0], term->rows);
> + move(term, term->curs.x,
> + term->curs.y + def(term->esc_args[0], 1), 1);
> + seen_disp_event(term);
> +@@ -3535,23 +3546,27 @@ static void term_out(Terminal *term)
> + compatibility(ANSI);
> + /* FALLTHROUGH */
> + case 'C': /* CUF: Cursor right */
> ++ CLAMP(term->esc_args[0], term->cols);
> + move(term, term->curs.x + def(term->esc_args[0],
> 1),
> + term->curs.y, 1);
> + seen_disp_event(term);
> + break;
> + case 'D': /* CUB: move left N cols */
> ++ CLAMP(term->esc_args[0], term->cols);
> + move(term, term->curs.x - def(term->esc_args[0],
> 1),
> + term->curs.y, 1);
> + seen_disp_event(term);
> + break;
> + case 'E': /* CNL: move down N lines and CR */
> + compatibility(ANSI);
> ++ CLAMP(term->esc_args[0], term->rows);
> + move(term, 0,
> + term->curs.y + def(term->esc_args[0], 1), 1);
> + seen_disp_event(term);
> + break;
> + case 'F': /* CPL: move up N lines and CR */
> + compatibility(ANSI);
> ++ CLAMP(term->esc_args[0], term->rows);
> + move(term, 0,
> + term->curs.y - def(term->esc_args[0], 1), 1);
> + seen_disp_event(term);
> +@@ -3559,12 +3574,14 @@ static void term_out(Terminal *term)
> + case 'G': /* CHA */
> + case '`': /* HPA: set horizontal posn */
> + compatibility(ANSI);
> ++ CLAMP(term->esc_args[0], term->cols);
> + move(term, def(term->esc_args[0], 1) - 1,
> + term->curs.y, 0);
> + seen_disp_event(term);
> + break;
> + case 'd': /* VPA: set vertical posn */
> + compatibility(ANSI);
> ++ CLAMP(term->esc_args[0], term->rows);
> + move(term, term->curs.x,
> + ((term->dec_om ? term->marg_t : 0) +
> + def(term->esc_args[0], 1) - 1),
> +@@ -3575,6 +3592,8 @@ static void term_out(Terminal *term)
> + case 'f': /* HVP: set horz and vert posns at
> once */
> + if (term->esc_nargs < 2)
> + term->esc_args[1] = ARG_DEFAULT;
> ++ CLAMP(term->esc_args[0], term->rows);
> ++ CLAMP(term->esc_args[1], term->cols);
> + move(term, def(term->esc_args[1], 1) - 1,
> + ((term->dec_om ? term->marg_t : 0) +
> + def(term->esc_args[0], 1) - 1),
> +@@ -3610,6 +3629,7 @@ static void term_out(Terminal *term)
> + break;
> + case 'L': /* IL: insert lines */
> + compatibility(VT102);
> ++ CLAMP(term->esc_args[0], term->rows);
> + if (term->curs.y <= term->marg_b)
> + scroll(term, term->curs.y, term->marg_b,
> + -def(term->esc_args[0], 1), FALSE);
> +@@ -3617,6 +3637,7 @@ static void term_out(Terminal *term)
> + break;
> + case 'M': /* DL: delete lines */
> + compatibility(VT102);
> ++ CLAMP(term->esc_args[0], term->rows);
> + if (term->curs.y <= term->marg_b)
> + scroll(term, term->curs.y, term->marg_b,
> + def(term->esc_args[0], 1),
> +@@ -3626,11 +3647,13 @@ static void term_out(Terminal *term)
> + case '@': /* ICH: insert chars */
> + /* XXX VTTEST says this is vt220, vt510 manual
> says vt102 */
> + compatibility(VT102);
> ++ CLAMP(term->esc_args[0], term->cols);
> + insch(term, def(term->esc_args[0], 1));
> + seen_disp_event(term);
> + break;
> + case 'P': /* DCH: delete chars */
> + compatibility(VT102);
> ++ CLAMP(term->esc_args[0], term->cols);
> + insch(term, -def(term->esc_args[0], 1));
> + seen_disp_event(term);
> + break;
> +@@ -3708,6 +3731,8 @@ static void term_out(Terminal *term)
> + compatibility(VT100);
> + if (term->esc_nargs <= 2) {
> + int top, bot;
> ++ CLAMP(term->esc_args[0], term->rows);
> ++ CLAMP(term->esc_args[1], term->rows);
> + top = def(term->esc_args[0], 1) - 1;
> + bot = (term->esc_nargs <= 1
> + || term->esc_args[1] == 0 ?
> +@@ -4062,6 +4087,7 @@ static void term_out(Terminal *term)
> + }
> + break;
> + case 'S': /* SU: Scroll up */
> ++ CLAMP(term->esc_args[0], term->rows);
> + compatibility(SCOANSI);
> + scroll(term, term->marg_t, term->marg_b,
> + def(term->esc_args[0], 1), TRUE);
> +@@ -4069,6 +4095,7 @@ static void term_out(Terminal *term)
> + seen_disp_event(term);
> + break;
> + case 'T': /* SD: Scroll down */
> ++ CLAMP(term->esc_args[0], term->rows);
> + compatibility(SCOANSI);
> + scroll(term, term->marg_t, term->marg_b,
> + -def(term->esc_args[0], 1), TRUE);
> +@@ -4111,6 +4138,7 @@ static void term_out(Terminal *term)
> + /* XXX VTTEST says this is vt220, vt510 manual
> + * says vt100 */
> + compatibility(ANSIMIN);
> ++ CLAMP(term->esc_args[0], term->cols);
> + {
> + int n = def(term->esc_args[0], 1);
> + pos cursplus;
> +@@ -4144,6 +4172,7 @@ static void term_out(Terminal *term)
> + break;
> + case 'Z': /* CBT */
> + compatibility(OTHER);
> ++ CLAMP(term->esc_args[0], term->cols);
> + {
> + int i = def(term->esc_args[0], 1);
> + pos old_curs = term->curs;
> +@@ -4204,7 +4233,7 @@ static void term_out(Terminal *term)
> + break;
> + case ANSI('F', '='): /* set normal foreground */
> + compatibility(SCOANSI);
> +- if (term->esc_args[0] >= 0 && term->esc_args[0] <
> 16) {
> ++ if (term->esc_args[0] < 16) {
> + long colour =
> + (sco2ansicolour[term->esc_args[0] & 0x7] |
> + (term->esc_args[0] & 0x8)) <<
> +@@ -4218,7 +4247,7 @@ static void term_out(Terminal *term)
> + break;
> + case ANSI('G', '='): /* set normal background */
> + compatibility(SCOANSI);
> +- if (term->esc_args[0] >= 0 && term->esc_args[0] <
> 16) {
> ++ if (term->esc_args[0] < 16) {
> + long colour =
> + (sco2ansicolour[term->esc_args[0] & 0x7] |
> + (term->esc_args[0] & 0x8)) <<
> +@@ -4342,7 +4371,11 @@ static void term_out(Terminal *term)
> + case '7':
> + case '8':
> + case '9':
> +- term->esc_args[0] = 10 * term->esc_args[0] + c - '0';
> ++ if (term->esc_args[0] <= UINT_MAX / 10 &&
> ++ term->esc_args[0] * 10 <= UINT_MAX - c - '0')
> ++ term->esc_args[0] = 10 * term->esc_args[0] + c -
> '0';
> ++ else
> ++ term->esc_args[0] = UINT_MAX;
> + break;
> + case 'L':
> + /*
> +@@ -4424,7 +4457,11 @@ static void term_out(Terminal *term)
> + case '7':
> + case '8':
> + case '9':
> +- term->esc_args[0] = 10 * term->esc_args[0] + c - '0';
> ++ if (term->esc_args[0] <= UINT_MAX / 10 &&
> ++ term->esc_args[0] * 10 <= UINT_MAX - c - '0')
> ++ term->esc_args[0] = 10 * term->esc_args[0] + c -
> '0';
> ++ else
> ++ term->esc_args[0] = UINT_MAX;
> + break;
> + default:
> + term->termstate = OSC_STRING;
> +diff --git a/terminal.h b/terminal.h
> +index 135ef45..01d5f57 100644
> +--- a/terminal.h
> ++++ b/terminal.h
> +@@ -172,7 +172,7 @@ struct terminal_tag {
> + #define ARGS_MAX 32 /* max # of esc sequence arguments
> */
> + #define ARG_DEFAULT 0 /* if an arg isn't specified */
> + #define def(a,d) ( (a) == ARG_DEFAULT ? (d) : (a) )
> +- int esc_args[ARGS_MAX];
> ++ unsigned esc_args[ARGS_MAX];
> + int esc_nargs;
> + int esc_query;
> + #define ANSI(x,y) ((x)+((y)<<8))
> +--
> +1.7.10.4
> +
> --
> 2.6.2
>
>