Merge pull request #16104 from denizzzka/avoid_overflow_ex_pr

Partial fix Bugzilla 15504 - core.demangle: remove OverflowException

Signed-off-by: Dennis <dkorpel@users.noreply.github.com>
Signed-off-by: Razvan Nitu <razvan.nitu1305@gmail.com>
Merged-on-behalf-of: Razvan Nitu <razvan.nitu1305@gmail.com>
This commit is contained in:
The Dlang Bot 2024-01-29 14:34:24 +01:00 committed by GitHub
commit 15ca454e80
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -118,10 +118,10 @@ pure @safe:
error(); error();
} }
char[] shift(scope const(char)[] val) return scope BufSlice shift(scope const BufSlice val) return scope
{ {
if (mute) if (mute)
return null; return dst.bslice_empty;
return dst.shift(val); return dst.shift(val);
} }
@ -138,6 +138,11 @@ pure @safe:
put(val[]); put(val[]);
} }
void put(scope BufSlice val) return scope
{
put(val.getSlice);
}
void put(scope const(char)[] val) return scope void put(scope const(char)[] val) return scope
{ {
if (mute) if (mute)
@ -671,7 +676,7 @@ pure @safe:
TypeTuple: TypeTuple:
B Number Arguments B Number Arguments
*/ */
char[] parseType() return scope BufSlice parseType() return scope
{ {
static immutable string[23] primitives = [ static immutable string[23] primitives = [
"char", // a "char", // a
@ -701,14 +706,14 @@ pure @safe:
static if (__traits(hasMember, Hooks, "parseType")) static if (__traits(hasMember, Hooks, "parseType"))
if (auto n = hooks.parseType(this, null)) if (auto n = hooks.parseType(this, null))
return n; return BufSlice(n, 0, n.length);
debug(trace) printf( "parseType+\n" ); debug(trace) printf( "parseType+\n" );
debug(trace) scope(success) printf( "parseType-\n" ); debug(trace) scope(success) printf( "parseType-\n" );
auto beg = dst.length; auto beg = dst.length;
auto t = front; auto t = front;
char[] parseBackrefType(scope char[] delegate() pure @safe parseDg) pure @safe BufSlice parseBackrefType(scope BufSlice delegate() pure @safe parseDg) pure @safe
{ {
if (pos == brp) if (pos == brp)
error("recursive back reference"); error("recursive back reference");
@ -718,7 +723,7 @@ pure @safe:
if (n == 0 || n > pos) if (n == 0 || n > pos)
error("invalid back reference"); error("invalid back reference");
if ( mute ) if ( mute )
return null; return dst.bslice_empty;
auto savePos = pos; auto savePos = pos;
auto saveBrp = brp; auto saveBrp = brp;
scope(success) { pos = savePos; brp = saveBrp; } scope(success) { pos = savePos; brp = saveBrp; }
@ -1215,7 +1220,7 @@ pure @safe:
TypeFunction: TypeFunction:
CallConvention FuncAttrs Arguments ArgClose Type CallConvention FuncAttrs Arguments ArgClose Type
*/ */
char[] parseTypeFunction(IsDelegate isdg = IsDelegate.no) return scope BufSlice parseTypeFunction(IsDelegate isdg = IsDelegate.no) return scope
{ {
debug(trace) printf( "parseTypeFunction+\n" ); debug(trace) printf( "parseTypeFunction+\n" );
debug(trace) scope(success) printf( "parseTypeFunction-\n" ); debug(trace) scope(success) printf( "parseTypeFunction-\n" );
@ -1297,7 +1302,13 @@ pure @safe:
E E
F F
*/ */
void parseValue(scope char[] name = null, char type = '\0' ) scope
void parseValue() scope
{
parseValue(dst.bslice_empty);
}
void parseValue(scope BufSlice name, char type = '\0' ) scope
{ {
debug(trace) printf( "parseValue+\n" ); debug(trace) printf( "parseValue+\n" );
debug(trace) scope(success) printf( "parseValue-\n" ); debug(trace) scope(success) printf( "parseValue-\n" );
@ -1423,8 +1434,12 @@ pure @safe:
} }
} }
void parseIntegerValue() scope
{
parseIntegerValue(dst.bslice_empty);
}
void parseIntegerValue( scope char[] name = null, char type = '\0' ) scope void parseIntegerValue( scope BufSlice name, char type = '\0' ) scope
{ {
debug(trace) printf( "parseIntegerValue+\n" ); debug(trace) printf( "parseIntegerValue+\n" );
debug(trace) scope(success) printf( "parseIntegerValue-\n" ); debug(trace) scope(success) printf( "parseIntegerValue-\n" );
@ -1562,7 +1577,7 @@ pure @safe:
char t = front; // peek at type for parseValue char t = front; // peek at type for parseValue
if ( t == 'Q' ) if ( t == 'Q' )
t = peekBackref(); t = peekBackref();
char[] name; silent( delegate void() { name = parseType(); } ); BufSlice name = dst.bslice_empty; silent( delegate void() { name = parseType(); } );
parseValue( name, t ); parseValue( name, t );
continue; continue;
case 'S': case 'S':
@ -1755,7 +1770,7 @@ pure @safe:
// parse optional function arguments as part of a symbol name, i.e without return type // parse optional function arguments as part of a symbol name, i.e without return type
// if keepAttr, the calling convention and function attributes are not discarded, but returned // if keepAttr, the calling convention and function attributes are not discarded, but returned
char[] parseFunctionTypeNoReturn( bool keepAttr = false ) return scope BufSlice parseFunctionTypeNoReturn( bool keepAttr = false ) return scope
{ {
// try to demangle a function, in case we are pointing to some function local // try to demangle a function, in case we are pointing to some function local
auto prevpos = pos; auto prevpos = pos;
@ -1777,7 +1792,7 @@ pure @safe:
} }
if ( isCallConvention( front ) ) if ( isCallConvention( front ) )
{ {
char[] attr; BufSlice attr = dst.bslice_empty;
// we don't want calling convention and attributes in the qualified name // we don't want calling convention and attributes in the qualified name
parseCallConvention(); parseCallConvention();
auto attributes = parseFuncAttr(); auto attributes = parseFuncAttr();
@ -1803,7 +1818,7 @@ pure @safe:
dst.len = prevlen; dst.len = prevlen;
brp = prevbrp; brp = prevbrp;
} }
return null; return dst.bslice_empty;
} }
/* /*
@ -1811,7 +1826,7 @@ pure @safe:
SymbolName SymbolName
SymbolName QualifiedName SymbolName QualifiedName
*/ */
char[] parseQualifiedName() return scope BufSlice parseQualifiedName() return scope
{ {
debug(trace) printf( "parseQualifiedName+\n" ); debug(trace) printf( "parseQualifiedName+\n" );
debug(trace) scope(success) printf( "parseQualifiedName-\n" ); debug(trace) scope(success) printf( "parseQualifiedName-\n" );
@ -1839,7 +1854,7 @@ pure @safe:
{ {
debug(trace) printf( "parseMangledName+\n" ); debug(trace) printf( "parseMangledName+\n" );
debug(trace) scope(success) printf( "parseMangledName-\n" ); debug(trace) scope(success) printf( "parseMangledName-\n" );
char[] name = null; BufSlice name = dst.bslice_empty;
auto end = pos + n; auto end = pos + n;
@ -1849,10 +1864,10 @@ pure @safe:
{ {
size_t beg = dst.length; size_t beg = dst.length;
size_t nameEnd = dst.length; size_t nameEnd = dst.length;
char[] attr; BufSlice attr = dst.bslice_empty;
do do
{ {
if ( attr ) if ( attr.length )
dst.remove(attr); // dump attributes of parent symbols dst.remove(attr); // dump attributes of parent symbols
if (beg != dst.length) if (beg != dst.length)
put( '.' ); put( '.' );
@ -1918,18 +1933,7 @@ pure @safe:
{ {
debug(info) printf( "demangle(%.*s)\n", cast(int) buf.length, buf.ptr ); debug(info) printf( "demangle(%.*s)\n", cast(int) buf.length, buf.ptr );
FUNC(); FUNC();
return dst[0 .. $]; return dst[0 .. $].getSlice;
}
catch ( OverflowException e )
{
debug(trace) printf( "overflow... restarting\n" );
auto a = Buffer.minSize;
auto b = 2 * dst.dst.length;
auto newsz = a < b ? b : a;
debug(info) printf( "growing dst to %lu bytes\n", newsz );
dst.dst.length = newsz;
pos = dst.len = brp = 0;
continue;
} }
catch ( ParseException e ) catch ( ParseException e )
{ {
@ -2117,7 +2121,7 @@ char[] reencodeMangled(return scope const(char)[] mangled) nothrow pure @safe
return true; return true;
} }
char[] parseType( ref Remangle d, char[] name = null ) return scope char[] parseType( ref Remangle d, char[] name ) return scope
{ {
if (d.front != 'Q') if (d.front != 'Q')
return null; return null;
@ -2849,15 +2853,6 @@ private class ParseException : Exception
} }
} }
/// Ditto
private class OverflowException : Exception
{
public this(string msg) @safe pure nothrow
{
super(msg);
}
}
/// Ditto /// Ditto
private noreturn error(string msg = "Invalid symbol") @trusted pure private noreturn error(string msg = "Invalid symbol") @trusted pure
{ {
@ -2869,16 +2864,6 @@ private noreturn error(string msg = "Invalid symbol") @trusted pure
: cast(ParseException) __traits(initSymbol, ParseException).ptr; : cast(ParseException) __traits(initSymbol, ParseException).ptr;
} }
/// Ditto
private noreturn overflow(string msg = "Buffer overflow") @trusted pure
{
version (DigitalMars) pragma(inline, false); // tame dmd inliner
//throw new OverflowException( msg );
debug(info) printf( "overflow: %.*s\n", cast(int) msg.length, msg.ptr );
throw cast(OverflowException) __traits(initSymbol, OverflowException).ptr;
}
private struct Buffer private struct Buffer
{ {
enum size_t minSize = 4000; enum size_t minSize = 4000;
@ -2895,23 +2880,17 @@ private struct Buffer
return this.len; return this.len;
} }
public inout(char)[] opSlice (size_t from, size_t to) public BufSlice opSlice (size_t from, size_t to)
inout return scope @safe pure nothrow @nogc return scope @safe pure nothrow @nogc
{ {
assert(from <= to); return bslice(from, to);
assert(to <= len);
return this.dst[from .. to];
} }
static bool contains(scope const(char)[] a, scope const(char)[] b) @trusted static bool contains(scope const(char)[] a, scope const BufSlice b) @safe
{ {
if (a.length && b.length) return
{ b.from < a.length &&
auto bend = b.ptr + b.length; b.to <= a.length;
auto aend = a.ptr + a.length;
return a.ptr <= b.ptr && bend <= aend;
}
return false;
} }
char[] copyInput(scope const(char)[] buf) char[] copyInput(scope const(char)[] buf)
@ -2924,46 +2903,62 @@ private struct Buffer
return r; return r;
} }
private void checkAndStretchBuf(size_t len_to_add) scope
{
const required = len + len_to_add;
if (required > dst.length)
dst.length = dst.length + len_to_add;
}
// move val to the end of the dst buffer // move val to the end of the dst buffer
char[] shift(scope const(char)[] val) return scope BufSlice shift(scope const BufSlice val) return scope
{ {
version (DigitalMars) pragma(inline, false); // tame dmd inliner version (DigitalMars) pragma(inline, false); // tame dmd inliner
if (val.length) if (val.length)
{ {
assert( contains( dst[0 .. len], val ) ); const ptrdiff_t s = val.from;
debug(info) printf( "shifting (%.*s)\n", cast(int) val.length, val.ptr ); const size_t f = len;
if (len + val.length > dst.length) assert(contains( dst[0 .. len], val ),
overflow(); "\ndst=\""~dst[0 .. len]~"\"\n"~
size_t v = &val[0] - &dst[0]; "val=\""~val.getSlice~"\"\n"
dst[len .. len + val.length] = val[]; );
for (size_t p = v; p < len; p++)
checkAndStretchBuf(val.length);
// store value temporary over len index
dst[len .. len + val.length] = val.getSlice();
// shift all chars including temporary saved above
// if buf was allocated above it will be leave for further usage
for (size_t p = s; p < f; p++)
dst[p] = dst[p + val.length]; dst[p] = dst[p + val.length];
return dst[len - val.length .. len]; return bslice(len - val.length, len);
} }
return null;
return bslice_empty;
} }
// remove val from dst buffer // remove val from dst buffer
void remove(scope const(char)[] val) scope void remove(scope BufSlice val) scope
{ {
version (DigitalMars) pragma(inline, false); // tame dmd inliner version (DigitalMars) pragma(inline, false); // tame dmd inliner
if ( val.length ) if ( val.length )
{ {
assert( contains( dst[0 .. len], val ) ); assert( contains( dst[0 .. len], val ) );
debug(info) printf( "removing (%.*s)\n", cast(int) val.length, val.ptr );
size_t v = &val[0] - &dst[0];
assert( len >= val.length && len <= dst.length ); assert( len >= val.length && len <= dst.length );
len -= val.length; len -= val.length;
for (size_t p = v; p < len; p++) for (size_t p = val.from; p < len; p++)
dst[p] = dst[p + val.length]; dst[p] = dst[p + val.length];
} }
} }
char[] append(scope const(char)[] val) return scope void append(scope const(char)[] val) scope
{ {
version (DigitalMars) pragma(inline, false); // tame dmd inliner version (DigitalMars) pragma(inline, false); // tame dmd inliner
@ -2971,25 +2966,78 @@ private struct Buffer
{ {
if ( !dst.length ) if ( !dst.length )
dst.length = minSize; dst.length = minSize;
assert( !contains( dst[0 .. len], val ) );
debug(info) printf( "appending (%.*s)\n", cast(int) val.length, val.ptr ); debug(info) printf( "appending (%.*s)\n", cast(int) val.length, val.ptr );
if ( dst.length - len >= val.length && &dst[len] == &val[0] ) checkAndStretchBuf(val.length);
{
// data is already in place // data is already not in place?
auto t = dst[len .. len + val.length]; if ( &dst[len] != &val[0] )
len += val.length;
return t;
}
if ( dst.length - len >= val.length )
{
dst[len .. len + val.length] = val[]; dst[len .. len + val.length] = val[];
auto t = dst[len .. len + val.length];
len += val.length; len += val.length;
return t;
}
overflow();
} }
return null; }
@nogc:
// from index to end of current buf
private scope bslice(size_t from) nothrow
{
return bslice(from, len);
}
private scope bslice(size_t from, size_t to) nothrow
{
return BufSlice(dst, from, to);
}
private scope bslice_empty() nothrow
{
return BufSlice(null, 0, 0);
} }
} }
private struct BufSlice
{
char[] dst;
@safe:
pure:
nothrow:
@disable this();
this(return scope char[] dst) scope nothrow @nogc
{
this(dst, 0, 0);
}
this(return scope char[] dst, size_t from, size_t to, bool lastArgIsLen = false) scope nothrow @nogc
{
this.dst = dst;
this.from = from;
if (lastArgIsLen)
this.to = from + to;
else
this.to = to;
}
size_t from;
size_t to;
invariant()
{
if (dst is null)
{
assert(from == 0);
assert(to == 0);
}
assert(from <= to);
}
auto getSlice() inout nothrow scope { return dst[from .. to]; }
size_t length() const scope { return to - from; }
}