Fix for CVE-2014-2270
Patch:
Code:
This patch is for php 5.5 code but works well enough on php 5.3 code.
Verified by hand that it patches the correct code.
Slightly modified by hand to remove unnecessary parts that fail to patch.
From a33759fd275b32ed0bbe89796fe2953b3cb0b41f Mon Sep 17 00:00:00 2001
From: Remi Collet <remi@php.net>
Date: Tue, 4 Mar 2014 20:32:52 +0100
Subject: [PATCH] Fixed Bug #66820 out-of-bounds memory access in fileinfo
Upstream fix:
Notice, test changed, with upstream agreement:
-define OFFSET_OOB(n, o, i) ((n) < (o) || (i) >= ((n) - (o)))
+define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o)))
---
ext/fileinfo/libmagic/softmagic.c | 34 ++++++++++++++++++----------------
1 file changed, 18 insertions(+), 16 deletions(-)
index 82a470a..21fea6b 100644
@@ -67,6 +67,8 @@ private void cvt_16(union VALUETYPE *, const struct magic *);
private void cvt_32(union VALUETYPE *, const struct magic *);
private void cvt_64(union VALUETYPE *, const struct magic *);
+#define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o)))
+
/*
* softmagic - lookup one file in parsed, in-memory copy of database
* Passed the name and FILE * of one file to be typed.
@@ -1171,7 +1173,7 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
}
switch (cvt_flip(m->in_type, flip)) {
case FILE_BYTE:
- if (nbytes < (offset + 1))
+ if (OFFSET_OOB(nbytes, offset, 1))
return 0;
if (off) {
switch (m->in_op & FILE_OPS_MASK) {
@@ -1206,7 +1208,7 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
offset = ~offset;
break;
case FILE_BESHORT:
- if (nbytes < (offset + 2))
+ if (OFFSET_OOB(nbytes, offset, 2))
return 0;
if (off) {
switch (m->in_op & FILE_OPS_MASK) {
@@ -1258,7 +1260,7 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
offset = ~offset;
break;
case FILE_LESHORT:
- if (nbytes < (offset + 2))
+ if (OFFSET_OOB(nbytes, offset, 2))
return 0;
if (off) {
switch (m->in_op & FILE_OPS_MASK) {
@@ -1310,7 +1312,7 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
offset = ~offset;
break;
case FILE_SHORT:
- if (nbytes < (offset + 2))
+ if (OFFSET_OOB(nbytes, offset, 2))
return 0;
if (off) {
switch (m->in_op & FILE_OPS_MASK) {
@@ -1347,7 +1349,7 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
break;
case FILE_BELONG:
case FILE_BEID3:
- if (nbytes < (offset + 4))
+ if (OFFSET_OOB(nbytes, offset, 4))
return 0;
if (off) {
switch (m->in_op & FILE_OPS_MASK) {
@@ -1418,7 +1420,7 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
break;
case FILE_LELONG:
case FILE_LEID3:
- if (nbytes < (offset + 4))
+ if (OFFSET_OOB(nbytes, offset, 4))
return 0;
if (off) {
switch (m->in_op & FILE_OPS_MASK) {
@@ -1488,7 +1490,7 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
offset = ~offset;
break;
case FILE_MELONG:
- if (nbytes < (offset + 4))
+ if (OFFSET_OOB(nbytes, offset, 4))
return 0;
if (off) {
switch (m->in_op & FILE_OPS_MASK) {
@@ -1558,7 +1560,7 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
offset = ~offset;
break;
case FILE_LONG:
- if (nbytes < (offset + 4))
+ if (OFFSET_OOB(nbytes, offset, 4))
return 0;
if (off) {
switch (m->in_op & FILE_OPS_MASK) {