Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
emacs
emacs
Commits
393d71f3
Commit
393d71f3
authored
Jun 16, 2011
by
Paul Eggert
Browse files
Improve buffer-overflow checking (Bug#8873).
parents
0cca0a78
4847e3f0
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
60 additions
and
57 deletions
+60
-57
src/ChangeLog
src/ChangeLog
+26
-0
src/buffer.h
src/buffer.h
+4
-2
src/editfns.c
src/editfns.c
+11
-16
src/fileio.c
src/fileio.c
+2
-11
src/insdel.c
src/insdel.c
+16
-28
src/lisp.h
src/lisp.h
+1
-0
No files found.
src/ChangeLog
View file @
393d71f3
2011-06-16 Paul Eggert <eggert@cs.ucla.edu>
Improve buffer-overflow checking (Bug#8873).
* fileio.c (Finsert_file_contents):
* insdel.c (insert_from_buffer_1, replace_range, replace_range_2):
Remove the old (too-loose) buffer overflow checks.
They weren't needed, since make_gap checks for buffer overflow.
* insdel.c (make_gap_larger): Catch buffer overflows that were missed.
The old code merely checked for Emacs fixnum overflow, and relied
on undefined (wraparound) behavior. The new code avoids undefined
behavior, and also checks for ptrdiff_t and/or size_t overflow.
* editfns.c (Finsert_char): Don't dump core with very negative counts.
Tune. Don't use wider integers than needed. Don't use alloca.
Use a bigger 'string' buffer. Rewrite to avoid 'n > 0' test.
* insdel.c (replace_range): Fix buf overflow when insbytes < outgoing.
* insdel.c, lisp.h (buffer_overflow): New function.
(insert_from_buffer_1, replace_range, replace_range_2):
* insdel.c (make_gap_larger):
* editfns.c (Finsert_char):
* fileio.c (Finsert_file_contents): Use it, to normalize wording.
* buffer.h (BUF_BYTES_MAX): Cast to ptrdiff_t so that it's signed.
2011-06-15 Paul Eggert <eggert@cs.ucla.edu>
Integer overflow and signedness fixes (Bug#8873).
...
...
src/buffer.h
View file @
393d71f3
...
...
@@ -309,8 +309,10 @@ while (0)
/* Maximum number of bytes in a buffer.
A buffer cannot contain more bytes than a 1-origin fixnum can represent,
nor can it be so large that C pointer arithmetic stops working. */
#define BUF_BYTES_MAX min (MOST_POSITIVE_FIXNUM - 1, min (SIZE_MAX, PTRDIFF_MAX))
nor can it be so large that C pointer arithmetic stops working.
The ptrdiff_t cast ensures that this is signed, not unsigned. */
#define BUF_BYTES_MAX \
(ptrdiff_t) min (MOST_POSITIVE_FIXNUM - 1, min (SIZE_MAX, PTRDIFF_MAX))
/* Return the address of byte position N in current buffer. */
...
...
src/editfns.c
View file @
393d71f3
...
...
@@ -2328,12 +2328,11 @@ The optional third arg INHERIT, if non-nil, says to inherit text properties
from adjoining text, if those properties are sticky. */
)
(
Lisp_Object
character
,
Lisp_Object
count
,
Lisp_Object
inherit
)
{
register
char
*
string
;
register
EMACS_INT
stringlen
;
register
int
i
;
int
i
,
stringlen
;
register
EMACS_INT
n
;
int
c
,
len
;
unsigned
char
str
[
MAX_MULTIBYTE_LENGTH
];
char
string
[
4000
];
CHECK_CHARACTER
(
character
);
CHECK_NUMBER
(
count
);
...
...
@@ -2343,16 +2342,15 @@ from adjoining text, if those properties are sticky. */)
len
=
CHAR_STRING
(
c
,
str
);
else
str
[
0
]
=
c
,
len
=
1
;
if
(
XINT
(
count
)
<=
0
)
return
Qnil
;
if
(
BUF_BYTES_MAX
/
len
<
XINT
(
count
))
error
(
"Maximum buffer size would be exceeded"
);
buffer_overflow
(
);
n
=
XINT
(
count
)
*
len
;
if
(
n
<=
0
)
return
Qnil
;
stringlen
=
min
(
n
,
256
*
len
);
string
=
(
char
*
)
alloca
(
stringlen
);
stringlen
=
min
(
n
,
sizeof
string
-
sizeof
string
%
len
);
for
(
i
=
0
;
i
<
stringlen
;
i
++
)
string
[
i
]
=
str
[
i
%
len
];
while
(
n
>
=
stringlen
)
while
(
n
>
stringlen
)
{
QUIT
;
if
(
!
NILP
(
inherit
))
...
...
@@ -2361,13 +2359,10 @@ from adjoining text, if those properties are sticky. */)
insert
(
string
,
stringlen
);
n
-=
stringlen
;
}
if
(
n
>
0
)
{
if
(
!
NILP
(
inherit
))
insert_and_inherit
(
string
,
n
);
else
insert
(
string
,
n
);
}
if
(
!
NILP
(
inherit
))
insert_and_inherit
(
string
,
n
);
else
insert
(
string
,
n
);
return
Qnil
;
}
...
...
src/fileio.c
View file @
393d71f3
...
...
@@ -3264,7 +3264,7 @@ variable `last-coding-system-used' to the coding system actually used. */)
platform that allows file sizes greater than the maximum off_t value. */
if
(
!
not_regular
&&
!
(
0
<=
st
.
st_size
&&
st
.
st_size
<=
BUF_BYTES_MAX
))
error
(
"Maximum buffer size exceeded"
);
buffer_overflow
(
);
/* Prevent redisplay optimizations. */
current_buffer
->
clip_changed
=
1
;
...
...
@@ -3800,16 +3800,7 @@ variable `last-coding-system-used' to the coding system actually used. */)
}
if
(
!
not_regular
)
{
register
Lisp_Object
temp
;
total
=
XINT
(
end
)
-
XINT
(
beg
);
/* Make sure point-max won't overflow after this insertion. */
XSETINT
(
temp
,
total
);
if
(
total
!=
XINT
(
temp
))
error
(
"Maximum buffer size exceeded"
);
}
total
=
XINT
(
end
)
-
XINT
(
beg
);
else
/* For a special file, all we can do is guess. */
total
=
READ_BUF_SIZE
;
...
...
src/insdel.c
View file @
393d71f3
...
...
@@ -391,6 +391,12 @@ adjust_markers_for_replace (EMACS_INT from, EMACS_INT from_byte,
}
void
buffer_overflow
(
void
)
{
error
(
"Maximum buffer size exceeded"
);
}
/* Make the gap NBYTES_ADDED bytes longer. */
static
void
...
...
@@ -400,16 +406,16 @@ make_gap_larger (EMACS_INT nbytes_added)
EMACS_INT
real_gap_loc
;
EMACS_INT
real_gap_loc_byte
;
EMACS_INT
old_gap_size
;
EMACS_INT
current_size
=
Z_BYTE
-
BEG_BYTE
+
GAP_SIZE
;
enum
{
enough_for_a_while
=
2000
};
/* If we have to get more space, get enough to last a while. */
nbytes_added
+=
2000
;
if
(
BUF_BYTES_MAX
-
current_size
<
nbytes_added
)
buffer_overflow
()
;
{
EMACS_INT
total_size
=
Z_BYTE
-
BEG_BYTE
+
GAP_SIZE
+
nbytes_added
;
if
(
total_size
<
0
/* Don't allow a buffer size that won't fit in a Lisp integer. */
||
total_size
!=
XINT
(
make_number
(
total_size
)))
error
(
"Buffer exceeds maximum size"
);
}
/* If we have to get more space, get enough to last a while;
but do not exceed the maximum buffer size. */
nbytes_added
=
min
(
nbytes_added
+
enough_for_a_while
,
BUF_BYTES_MAX
-
current_size
);
enlarge_buffer_text
(
current_buffer
,
nbytes_added
);
...
...
@@ -1063,7 +1069,6 @@ static void
insert_from_buffer_1
(
struct
buffer
*
buf
,
EMACS_INT
from
,
EMACS_INT
nchars
,
int
inherit
)
{
register
Lisp_Object
temp
;
EMACS_INT
chunk
,
chunk_expanded
;
EMACS_INT
from_byte
=
buf_charpos_to_bytepos
(
buf
,
from
);
EMACS_INT
to_byte
=
buf_charpos_to_bytepos
(
buf
,
from
+
nchars
);
...
...
@@ -1102,11 +1107,6 @@ insert_from_buffer_1 (struct buffer *buf,
outgoing_nbytes
=
outgoing_before_gap
+
outgoing_after_gap
;
}
/* Make sure point-max won't overflow after this insertion. */
XSETINT
(
temp
,
outgoing_nbytes
+
Z
);
if
(
outgoing_nbytes
+
Z
!=
XINT
(
temp
))
error
(
"Maximum buffer size exceeded"
);
/* Do this before moving and increasing the gap,
because the before-change hooks might move the gap
or make it smaller. */
...
...
@@ -1303,7 +1303,6 @@ replace_range (EMACS_INT from, EMACS_INT to, Lisp_Object new,
EMACS_INT
insbytes
=
SBYTES
(
new
);
EMACS_INT
from_byte
,
to_byte
;
EMACS_INT
nbytes_del
,
nchars_del
;
register
Lisp_Object
temp
;
struct
gcpro
gcpro1
;
INTERVAL
intervals
;
EMACS_INT
outgoing_insbytes
=
insbytes
;
...
...
@@ -1347,11 +1346,6 @@ replace_range (EMACS_INT from, EMACS_INT to, Lisp_Object new,
outgoing_insbytes
=
count_size_as_multibyte
(
SDATA
(
new
),
insbytes
);
/* Make sure point-max won't overflow after this insertion. */
XSETINT
(
temp
,
Z_BYTE
-
nbytes_del
+
insbytes
);
if
(
Z_BYTE
-
nbytes_del
+
insbytes
!=
XINT
(
temp
))
error
(
"Maximum buffer size exceeded"
);
GCPRO1
(
new
);
/* Make sure the gap is somewhere in or next to what we are deleting. */
...
...
@@ -1383,8 +1377,8 @@ replace_range (EMACS_INT from, EMACS_INT to, Lisp_Object new,
if
(
Z
-
GPT
<
END_UNCHANGED
)
END_UNCHANGED
=
Z
-
GPT
;
if
(
GAP_SIZE
<
insbytes
)
make_gap
(
insbytes
-
GAP_SIZE
);
if
(
GAP_SIZE
<
outgoing_
insbytes
)
make_gap
(
outgoing_
insbytes
-
GAP_SIZE
);
/* Copy the string text into the buffer, perhaps converting
between single-byte and multibyte. */
...
...
@@ -1482,7 +1476,6 @@ replace_range_2 (EMACS_INT from, EMACS_INT from_byte,
int
markers
)
{
EMACS_INT
nbytes_del
,
nchars_del
;
Lisp_Object
temp
;
CHECK_MARKERS
();
...
...
@@ -1492,11 +1485,6 @@ replace_range_2 (EMACS_INT from, EMACS_INT from_byte,
if
(
nbytes_del
<=
0
&&
insbytes
==
0
)
return
;
/* Make sure point-max won't overflow after this insertion. */
XSETINT
(
temp
,
Z_BYTE
-
nbytes_del
+
insbytes
);
if
(
Z_BYTE
-
nbytes_del
+
insbytes
!=
XINT
(
temp
))
error
(
"Maximum buffer size exceeded"
);
/* Make sure the gap is somewhere in or next to what we are deleting. */
if
(
from
>
GPT
)
gap_right
(
from
,
from_byte
);
...
...
src/lisp.h
View file @
393d71f3
...
...
@@ -2635,6 +2635,7 @@ extern void init_image (void);
extern
Lisp_Object
Qinhibit_modification_hooks
;
extern
void
move_gap
(
EMACS_INT
);
extern
void
move_gap_both
(
EMACS_INT
,
EMACS_INT
);
extern
void
buffer_overflow
(
void
)
NO_RETURN
;
extern
void
make_gap
(
EMACS_INT
);
extern
EMACS_INT
copy_text
(
const
unsigned
char
*
,
unsigned
char
*
,
EMACS_INT
,
int
,
int
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment