mirror of
https://github.com/dlang/phobos.git
synced 2025-04-29 14:40:30 +03:00
Use LockedFile struct to enforce safe interface
Instead of wrong trusted_FUNLOCK. Note: trusted_FGETC does have a @safe interface.
This commit is contained in:
parent
9f05dd4d4a
commit
b036f74ef2
1 changed files with 55 additions and 24 deletions
77
std/stdio.d
77
std/stdio.d
|
@ -5455,23 +5455,61 @@ private struct ReadlnAppender
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private implementation of readln
|
private struct LockedFile
|
||||||
private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orientation orientation) @safe
|
|
||||||
{
|
{
|
||||||
alias trusted_FLOCK = (fps) @trusted => _FLOCK(fps);
|
private @system FILE* fps;
|
||||||
alias trusted_FUNLOCK = (fps) @trusted => _FUNLOCK(fps);
|
|
||||||
alias trusted_FGETC = (fp) @trusted => _FGETC(fp);
|
|
||||||
alias trusted_FGETWC = (fp) @trusted => _FGETWC(fp);
|
|
||||||
|
|
||||||
version (DIGITAL_MARS_STDIO)
|
this(FILE* fps) @trusted
|
||||||
{
|
{
|
||||||
trusted_FLOCK(fps);
|
this.fps = fps;
|
||||||
scope(exit) trusted_FUNLOCK(fps);
|
_FLOCK(fps);
|
||||||
|
}
|
||||||
|
|
||||||
|
@disable this();
|
||||||
|
@disable this(this);
|
||||||
|
@disable void opAssign(LockedFile);
|
||||||
|
|
||||||
/* Since fps is now locked, we can create an "unshared" version
|
/* Since fps is now locked, we can create an "unshared" version
|
||||||
* of fp.
|
* of fp.
|
||||||
*/
|
*/
|
||||||
auto fp = (() @trusted => cast(_iobuf*) fps)();
|
@trusted fp() return scope => cast(_iobuf*) fps;
|
||||||
|
|
||||||
|
~this() @trusted
|
||||||
|
{
|
||||||
|
_FUNLOCK(fps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
_iobuf* f() @safe
|
||||||
|
{
|
||||||
|
FILE* fps;
|
||||||
|
auto lf = LockedFile(fps);
|
||||||
|
scope fp = lf.fp;
|
||||||
|
static assert(!__traits(compiles, lf = LockedFile(fps)));
|
||||||
|
static assert(!__traits(compiles, { if (fps) return fp; }));
|
||||||
|
version (ShouldFail)
|
||||||
|
{
|
||||||
|
lf.destroy; // fail in @safe because of @system field?
|
||||||
|
auto x = fp; // demonstrates use after unlock
|
||||||
|
lf.fps = null; // @system field
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private implementation of readln
|
||||||
|
private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orientation orientation) @safe
|
||||||
|
{
|
||||||
|
// fp is not shared so these calls are safe
|
||||||
|
alias trusted_FGETC = (scope _iobuf* fp) @trusted => _FGETC(fp);
|
||||||
|
alias trusted_FGETWC = (scope _iobuf* fp) @trusted => _FGETWC(fp);
|
||||||
|
|
||||||
|
version (DIGITAL_MARS_STDIO)
|
||||||
|
{
|
||||||
|
auto lf = LockedFile(fps);
|
||||||
|
auto fp = lf.fp;
|
||||||
|
|
||||||
ReadlnAppender app;
|
ReadlnAppender app;
|
||||||
app.initialize(buf);
|
app.initialize(buf);
|
||||||
|
@ -5586,13 +5624,8 @@ private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orie
|
||||||
}
|
}
|
||||||
else version (MICROSOFT_STDIO)
|
else version (MICROSOFT_STDIO)
|
||||||
{
|
{
|
||||||
trusted_FLOCK(fps);
|
auto lf = LockedFile(fps);
|
||||||
scope(exit) trusted_FUNLOCK(fps);
|
auto fp = lf.fp;
|
||||||
|
|
||||||
/* Since fps is now locked, we can create an "unshared" version
|
|
||||||
* of fp.
|
|
||||||
*/
|
|
||||||
auto fp = (() @trusted => cast(_iobuf*) fps)();
|
|
||||||
|
|
||||||
ReadlnAppender app;
|
ReadlnAppender app;
|
||||||
app.initialize(buf);
|
app.initialize(buf);
|
||||||
|
@ -5621,12 +5654,11 @@ private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orie
|
||||||
|
|
||||||
if (orientation == File.Orientation.wide)
|
if (orientation == File.Orientation.wide)
|
||||||
{
|
{
|
||||||
|
auto lf = LockedFile(fps);
|
||||||
|
auto fp = lf.fp;
|
||||||
/* Stream is in wide characters.
|
/* Stream is in wide characters.
|
||||||
* Read them and convert to chars.
|
* Read them and convert to chars.
|
||||||
*/
|
*/
|
||||||
trusted_FLOCK(fps);
|
|
||||||
scope(exit) trusted_FUNLOCK(fps);
|
|
||||||
auto fp = (() @trusted => cast(_iobuf*) fps)();
|
|
||||||
version (Windows)
|
version (Windows)
|
||||||
{
|
{
|
||||||
buf.length = 0;
|
buf.length = 0;
|
||||||
|
@ -5719,9 +5751,8 @@ private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orie
|
||||||
{
|
{
|
||||||
import core.stdc.wchar_ : fwide;
|
import core.stdc.wchar_ : fwide;
|
||||||
|
|
||||||
trusted_FLOCK(fps);
|
auto lf = LockedFile(fps);
|
||||||
scope(exit) trusted_FUNLOCK(fps);
|
auto fp = lf.fp;
|
||||||
auto fp = (() @trusted => cast(_iobuf*) fps)();
|
|
||||||
if (orientation == File.Orientation.wide)
|
if (orientation == File.Orientation.wide)
|
||||||
{
|
{
|
||||||
/* Stream is in wide characters.
|
/* Stream is in wide characters.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue