diff --git a/src/libexpr/attr-set.cc b/src/libexpr/attr-set.cc index 6e958581b..ef756f1d8 100644 --- a/src/libexpr/attr-set.cc +++ b/src/libexpr/attr-set.cc @@ -12,7 +12,7 @@ namespace nix { Bindings structure. */ Ptr Bindings::allocBindings(size_t capacity) { - if (capacity >= 1UL << Object::miscBits) + if (capacity >= 1UL << Object::miscBytes * 8) throw Error("attribute set of size %d is too big", capacity); return gc.alloc(Bindings::wordsFor(capacity), capacity); } diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 2ded61e24..99ada041f 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -497,10 +497,9 @@ LocalNoInline(void addErrorPrefix(Error & e, const char * s, const string & s2, void mkString(Value & v, const char * s) { auto len = strlen(s); // FIXME: only need to know if > short - if (len < WORD_SIZE * 2) { - strcpy((char *) &v.string, s); - v.type = tShortString; - } else + if (len < WORD_SIZE * 2 + Object::miscBytes) + v.setShortString(s); + else mkStringNoCopy(v, dupString(s)); } diff --git a/src/libexpr/gc.hh b/src/libexpr/gc.hh index d740572ce..a0ca3f307 100644 --- a/src/libexpr/gc.hh +++ b/src/libexpr/gc.hh @@ -51,17 +51,16 @@ struct Object friend class GC; public: - constexpr static unsigned int miscBits = 58; - -private: - unsigned long misc:58; + constexpr static size_t miscBytes = 7; public: // FIXME - Tag type:5; + Tag type:7; private: bool marked:1; + unsigned long misc:56; + void unmark() { marked = false; @@ -69,7 +68,7 @@ private: protected: - Object(Tag type, unsigned long misc) : misc(misc), type(type), marked(false) { } + Object(Tag type, unsigned long misc) : type(type), marked(false), misc(misc) { } bool isMarked() { @@ -90,6 +89,11 @@ protected: { return misc; } + + char * getMiscData() const + { + return ((char *) this) + 1; + } }; template diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh index d24656e80..2289b86fd 100644 --- a/src/libexpr/value.hh +++ b/src/libexpr/value.hh @@ -3,6 +3,8 @@ #include "symbol-table.hh" #include "gc.hh" +#include + namespace nix { class Bindings; @@ -203,10 +205,18 @@ public: return type == tShortString || type == tLongString; } + void setShortString(const char * s) + { + // FIXME: can't use strcpy here because gcc flags it as a + // buffer overflow on 'misc'. + memcpy(getMiscData(), s, strlen(s) + 1); + type = tShortString; + } + const char * getString() const { if (type == tShortString) - return (const char *) &string; + return getMiscData(); else return string._s; }