mirror of
https://github.com/janet-lang/janet
synced 2024-12-26 00:10:27 +00:00
Fix use after free bug in buffer/format when printing self.
This commit is contained in:
parent
bfb0cb331e
commit
bbcfaf1289
@ -198,8 +198,15 @@ void janet_description_b(JanetBuffer *buffer, Janet x) {
|
|||||||
janet_escape_string_b(buffer, janet_unwrap_string(x));
|
janet_escape_string_b(buffer, janet_unwrap_string(x));
|
||||||
return;
|
return;
|
||||||
case JANET_BUFFER:
|
case JANET_BUFFER:
|
||||||
janet_escape_buffer_b(buffer, janet_unwrap_buffer(x));
|
{
|
||||||
return;
|
JanetBuffer *b = janet_unwrap_buffer(x);
|
||||||
|
if (b == buffer) {
|
||||||
|
/* Ensures buffer won't resize while escaping */
|
||||||
|
janet_buffer_ensure(b, 5 * b->count + 3, 1);
|
||||||
|
}
|
||||||
|
janet_escape_buffer_b(buffer, b);
|
||||||
|
return;
|
||||||
|
}
|
||||||
case JANET_ABSTRACT: {
|
case JANET_ABSTRACT: {
|
||||||
void *p = janet_unwrap_abstract(x);
|
void *p = janet_unwrap_abstract(x);
|
||||||
const JanetAbstractType *at = janet_abstract_type(p);
|
const JanetAbstractType *at = janet_abstract_type(p);
|
||||||
@ -298,6 +305,7 @@ struct pretty {
|
|||||||
int depth;
|
int depth;
|
||||||
int indent;
|
int indent;
|
||||||
int flags;
|
int flags;
|
||||||
|
int32_t bufstartlen;
|
||||||
JanetTable seen;
|
JanetTable seen;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -372,7 +380,13 @@ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) {
|
|||||||
if (color && (S->flags & JANET_PRETTY_COLOR)) {
|
if (color && (S->flags & JANET_PRETTY_COLOR)) {
|
||||||
janet_buffer_push_cstring(S->buffer, color);
|
janet_buffer_push_cstring(S->buffer, color);
|
||||||
}
|
}
|
||||||
janet_description_b(S->buffer, x);
|
if (janet_checktype(x, JANET_BUFFER) && janet_unwrap_buffer(x) == S->buffer) {
|
||||||
|
janet_buffer_ensure(S->buffer, S->buffer->count + S->bufstartlen * 4 + 3, 1);
|
||||||
|
janet_buffer_push_u8(S->buffer, '@');
|
||||||
|
janet_escape_string_impl(S->buffer, S->buffer->data, S->bufstartlen);
|
||||||
|
} else {
|
||||||
|
janet_description_b(S->buffer, x);
|
||||||
|
}
|
||||||
if (color && (S->flags & JANET_PRETTY_COLOR)) {
|
if (color && (S->flags & JANET_PRETTY_COLOR)) {
|
||||||
janet_buffer_push_cstring(S->buffer, "\x1B[0m");
|
janet_buffer_push_cstring(S->buffer, "\x1B[0m");
|
||||||
}
|
}
|
||||||
@ -461,9 +475,7 @@ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper for printing a janet value in a pretty form. Not meant to be used
|
static JanetBuffer *janet_pretty_(JanetBuffer *buffer, int depth, int flags, Janet x, int32_t startlen) {
|
||||||
* for serialization or anything like that. */
|
|
||||||
JanetBuffer *janet_pretty(JanetBuffer *buffer, int depth, int flags, Janet x) {
|
|
||||||
struct pretty S;
|
struct pretty S;
|
||||||
if (NULL == buffer) {
|
if (NULL == buffer) {
|
||||||
buffer = janet_buffer(0);
|
buffer = janet_buffer(0);
|
||||||
@ -472,12 +484,19 @@ JanetBuffer *janet_pretty(JanetBuffer *buffer, int depth, int flags, Janet x) {
|
|||||||
S.depth = depth;
|
S.depth = depth;
|
||||||
S.indent = 0;
|
S.indent = 0;
|
||||||
S.flags = flags;
|
S.flags = flags;
|
||||||
|
S.bufstartlen = startlen;
|
||||||
janet_table_init(&S.seen, 10);
|
janet_table_init(&S.seen, 10);
|
||||||
janet_pretty_one(&S, x, 0);
|
janet_pretty_one(&S, x, 0);
|
||||||
janet_table_deinit(&S.seen);
|
janet_table_deinit(&S.seen);
|
||||||
return S.buffer;
|
return S.buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper for printing a janet value in a pretty form. Not meant to be used
|
||||||
|
* for serialization or anything like that. */
|
||||||
|
JanetBuffer *janet_pretty(JanetBuffer *buffer, int depth, int flags, Janet x) {
|
||||||
|
return janet_pretty_(buffer, depth, flags, x, buffer ? buffer->count : 0);
|
||||||
|
}
|
||||||
|
|
||||||
static const char *typestr(Janet x) {
|
static const char *typestr(Janet x) {
|
||||||
JanetType t = janet_type(x);
|
JanetType t = janet_type(x);
|
||||||
return (t == JANET_ABSTRACT)
|
return (t == JANET_ABSTRACT)
|
||||||
@ -643,6 +662,7 @@ void janet_buffer_format(
|
|||||||
size_t sfl = strlen(strfrmt);
|
size_t sfl = strlen(strfrmt);
|
||||||
const char *strfrmt_end = strfrmt + sfl;
|
const char *strfrmt_end = strfrmt + sfl;
|
||||||
int32_t arg = argstart;
|
int32_t arg = argstart;
|
||||||
|
int32_t startlen = b->count;
|
||||||
while (strfrmt < strfrmt_end) {
|
while (strfrmt < strfrmt_end) {
|
||||||
if (*strfrmt != '%')
|
if (*strfrmt != '%')
|
||||||
janet_buffer_push_u8(b, (uint8_t) * strfrmt++);
|
janet_buffer_push_u8(b, (uint8_t) * strfrmt++);
|
||||||
@ -711,7 +731,7 @@ void janet_buffer_format(
|
|||||||
int depth = atoi(precision);
|
int depth = atoi(precision);
|
||||||
if (depth < 1)
|
if (depth < 1)
|
||||||
depth = 4;
|
depth = 4;
|
||||||
janet_pretty(b, depth, (strfrmt[-1] == 'P') ? JANET_PRETTY_COLOR : 0, argv[arg]);
|
janet_pretty_(b, depth, (strfrmt[-1] == 'P') ? JANET_PRETTY_COLOR : 0, argv[arg], startlen);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
@ -46,14 +46,6 @@
|
|||||||
|
|
||||||
(assert (= txs '[[-1 -1] [-1 0] [-1 1] [0 -1] [0 1] [1 -1] [1 0] [1 1]]) "nested seq")
|
(assert (= txs '[[-1 -1] [-1 0] [-1 1] [0 -1] [0 1] [1 -1] [1 0] [1 1]]) "nested seq")
|
||||||
|
|
||||||
# Buffer self blitting, check for use after free
|
|
||||||
(def buf1 @"1234567890")
|
|
||||||
(buffer/blit buf1 buf1 -1)
|
|
||||||
(buffer/blit buf1 buf1 -1)
|
|
||||||
(buffer/blit buf1 buf1 -1)
|
|
||||||
(buffer/blit buf1 buf1 -1)
|
|
||||||
(assert (= (string buf1) (string/repeat "1234567890" 16)) "buffer blit against self")
|
|
||||||
|
|
||||||
# Generators
|
# Generators
|
||||||
(def gen (generate [x :range [0 100] :when (pos? (% x 4))] x))
|
(def gen (generate [x :range [0 100] :when (pos? (% x 4))] x))
|
||||||
(var gencount 0)
|
(var gencount 0)
|
||||||
|
@ -159,6 +159,14 @@
|
|||||||
(buffer/blit b2 "abcdefg" 5 6)
|
(buffer/blit b2 "abcdefg" 5 6)
|
||||||
(assert (= (string b2) "joytogjoyto") "buffer/blit 3")
|
(assert (= (string b2) "joytogjoyto") "buffer/blit 3")
|
||||||
|
|
||||||
|
# Buffer self blitting, check for use after free
|
||||||
|
(def buf1 @"1234567890")
|
||||||
|
(buffer/blit buf1 buf1 -1)
|
||||||
|
(buffer/blit buf1 buf1 -1)
|
||||||
|
(buffer/blit buf1 buf1 -1)
|
||||||
|
(buffer/blit buf1 buf1 -1)
|
||||||
|
(assert (= (string buf1) (string/repeat "1234567890" 16)) "buffer blit against self")
|
||||||
|
|
||||||
# Buffer push word
|
# Buffer push word
|
||||||
|
|
||||||
(def b3 @"")
|
(def b3 @"")
|
||||||
@ -179,6 +187,13 @@
|
|||||||
(buffer/push-string b5 "456" @"789")
|
(buffer/push-string b5 "456" @"789")
|
||||||
(assert (= "123456789" (string b5)) "buffer/push-buffer 2")
|
(assert (= "123456789" (string b5)) "buffer/push-buffer 2")
|
||||||
|
|
||||||
|
# Check for bugs with printing self with buffer/format
|
||||||
|
|
||||||
|
(def buftemp @"abcd")
|
||||||
|
(assert (= (string (buffer/format buftemp "---%p---" buftemp)) `abcd---@"abcd"---`) "buffer/format on self 1")
|
||||||
|
(def buftemp @"abcd")
|
||||||
|
(assert (= (string (buffer/format buftemp "---%p %p---" buftemp buftemp)) `abcd---@"abcd" @"abcd"---`) "buffer/format on self 2")
|
||||||
|
|
||||||
# Peg
|
# Peg
|
||||||
|
|
||||||
(defn check-match
|
(defn check-match
|
||||||
|
Loading…
Reference in New Issue
Block a user