Skip to content

Commit

Permalink
0.531 (#532)
Browse files Browse the repository at this point in the history
* Fix free Luau type being fully overwritten by 'any' and causing UAF
* Fix lua_clonefunction implementation replacing top instead of pushing
* Falsey values other than false can now narrow refinements
* Fix lua_getmetatable, lua_getfenv not waking thread up
* FIx a case where lua_objlen could push a new string without thread wakeup or GC
* Moved Luau math and bit32 definitions to definition file 
* Improve Luau parse recovery of incorrect return type token
  • Loading branch information
rblanckaert committed Jun 10, 2022
1 parent ca5fbbf commit b066e4c
Show file tree
Hide file tree
Showing 33 changed files with 525 additions and 458 deletions.
13 changes: 12 additions & 1 deletion Analysis/include/Luau/TypePack.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,24 @@ struct TypePackVar
explicit TypePackVar(const TypePackVariant& ty);
explicit TypePackVar(TypePackVariant&& ty);
TypePackVar(TypePackVariant&& ty, bool persistent);

bool operator==(const TypePackVar& rhs) const;

TypePackVar& operator=(TypePackVariant&& tp);

TypePackVar& operator=(const TypePackVar& rhs);

// Re-assignes the content of the pack, but doesn't change the owning arena and can't make pack persistent.
void reassign(const TypePackVar& rhs)
{
ty = rhs.ty;
}

TypePackVariant ty;

bool persistent = false;

// Pointer to the type arena that allocated this type.
// Pointer to the type arena that allocated this pack.
TypeArena* owningArena = nullptr;
};

Expand Down
11 changes: 10 additions & 1 deletion Analysis/include/Luau/TypeVar.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,6 @@ struct TableTypeVar
// We need to know which is which when we stringify types.
std::optional<std::string> syntheticName;

std::map<Name, Location> methodDefinitionLocations; // TODO: Remove with FFlag::LuauNoMethodLocations
std::vector<TypeId> instantiatedTypeParams;
std::vector<TypePackId> instantiatedTypePackParams;
ModuleName definitionModuleName;
Expand Down Expand Up @@ -465,6 +464,14 @@ struct TypeVar final
{
}

// Re-assignes the content of the type, but doesn't change the owning arena and can't make type persistent.
void reassign(const TypeVar& rhs)
{
ty = rhs.ty;
normal = rhs.normal;
documentationSymbol = rhs.documentationSymbol;
}

TypeVariant ty;

// Kludge: A persistent TypeVar is one that belongs to the global scope.
Expand All @@ -486,6 +493,8 @@ struct TypeVar final

TypeVar& operator=(const TypeVariant& rhs);
TypeVar& operator=(TypeVariant&& rhs);

TypeVar& operator=(const TypeVar& rhs);
};

using SeenSet = std::set<std::pair<const void*, const void*>>;
Expand Down
41 changes: 22 additions & 19 deletions Analysis/src/Autocomplete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
#include <utility>

LUAU_FASTFLAGVARIABLE(LuauIfElseExprFixCompletionIssue, false);
LUAU_FASTFLAGVARIABLE(LuauFixAutocompleteClassSecurityLevel, false);
LUAU_FASTFLAG(LuauSelfCallAutocompleteFix)
LUAU_FASTFLAG(LuauSelfCallAutocompleteFix2)

static const std::unordered_set<std::string> kStatementStartingKeywords = {
"while", "if", "local", "repeat", "function", "do", "for", "return", "break", "continue", "type", "export"};
Expand Down Expand Up @@ -248,7 +247,7 @@ static TypeCorrectKind checkTypeCorrectKind(const Module& module, TypeArena* typ
ty = follow(ty);

auto canUnify = [&typeArena](TypeId subTy, TypeId superTy) {
LUAU_ASSERT(!FFlag::LuauSelfCallAutocompleteFix);
LUAU_ASSERT(!FFlag::LuauSelfCallAutocompleteFix2);

InternalErrorReporter iceReporter;
UnifierSharedState unifierState(&iceReporter);
Expand All @@ -267,7 +266,7 @@ static TypeCorrectKind checkTypeCorrectKind(const Module& module, TypeArena* typ
TypeId expectedType = follow(*typeAtPosition);

auto checkFunctionType = [typeArena, &canUnify, &expectedType](const FunctionTypeVar* ftv) {
if (FFlag::LuauSelfCallAutocompleteFix)
if (FFlag::LuauSelfCallAutocompleteFix2)
{
if (std::optional<TypeId> firstRetTy = first(ftv->retType))
return checkTypeMatch(typeArena, *firstRetTy, expectedType);
Expand Down Expand Up @@ -308,7 +307,7 @@ static TypeCorrectKind checkTypeCorrectKind(const Module& module, TypeArena* typ
}
}

if (FFlag::LuauSelfCallAutocompleteFix)
if (FFlag::LuauSelfCallAutocompleteFix2)
return checkTypeMatch(typeArena, ty, expectedType) ? TypeCorrectKind::Correct : TypeCorrectKind::None;
else
return canUnify(ty, expectedType) ? TypeCorrectKind::Correct : TypeCorrectKind::None;
Expand All @@ -325,7 +324,7 @@ static void autocompleteProps(const Module& module, TypeArena* typeArena, TypeId
const std::vector<AstNode*>& nodes, AutocompleteEntryMap& result, std::unordered_set<TypeId>& seen,
std::optional<const ClassTypeVar*> containingClass = std::nullopt)
{
if (FFlag::LuauSelfCallAutocompleteFix)
if (FFlag::LuauSelfCallAutocompleteFix2)
rootTy = follow(rootTy);

ty = follow(ty);
Expand All @@ -335,7 +334,7 @@ static void autocompleteProps(const Module& module, TypeArena* typeArena, TypeId
seen.insert(ty);

auto isWrongIndexer_DEPRECATED = [indexType, useStrictFunctionIndexers = !!get<ClassTypeVar>(ty)](Luau::TypeId type) {
LUAU_ASSERT(!FFlag::LuauSelfCallAutocompleteFix);
LUAU_ASSERT(!FFlag::LuauSelfCallAutocompleteFix2);

if (indexType == PropIndexType::Key)
return false;
Expand Down Expand Up @@ -368,7 +367,7 @@ static void autocompleteProps(const Module& module, TypeArena* typeArena, TypeId
}
};
auto isWrongIndexer = [typeArena, rootTy, indexType](Luau::TypeId type) {
LUAU_ASSERT(FFlag::LuauSelfCallAutocompleteFix);
LUAU_ASSERT(FFlag::LuauSelfCallAutocompleteFix2);

if (indexType == PropIndexType::Key)
return false;
Expand All @@ -382,10 +381,15 @@ static void autocompleteProps(const Module& module, TypeArena* typeArena, TypeId
return calledWithSelf == ftv->hasSelf;
}

if (std::optional<TypeId> firstArgTy = first(ftv->argTypes))
// If a call is made with ':', it is invalid if a function has incompatible first argument or no arguments at all
// If a call is made with '.', but it was declared with 'self', it is considered invalid if first argument is compatible
if (calledWithSelf || ftv->hasSelf)
{
if (checkTypeMatch(typeArena, rootTy, *firstArgTy))
return calledWithSelf;
if (std::optional<TypeId> firstArgTy = first(ftv->argTypes))
{
if (checkTypeMatch(typeArena, rootTy, *firstArgTy))
return calledWithSelf;
}
}

return !calledWithSelf;
Expand Down Expand Up @@ -427,7 +431,7 @@ static void autocompleteProps(const Module& module, TypeArena* typeArena, TypeId
AutocompleteEntryKind::Property,
type,
prop.deprecated,
FFlag::LuauSelfCallAutocompleteFix ? isWrongIndexer(type) : isWrongIndexer_DEPRECATED(type),
FFlag::LuauSelfCallAutocompleteFix2 ? isWrongIndexer(type) : isWrongIndexer_DEPRECATED(type),
typeCorrect,
containingClass,
&prop,
Expand Down Expand Up @@ -462,16 +466,15 @@ static void autocompleteProps(const Module& module, TypeArena* typeArena, TypeId
containingClass = containingClass.value_or(cls);
fillProps(cls->props);
if (cls->parent)
autocompleteProps(module, typeArena, rootTy, *cls->parent, indexType, nodes, result, seen,
FFlag::LuauFixAutocompleteClassSecurityLevel ? containingClass : cls);
autocompleteProps(module, typeArena, rootTy, *cls->parent, indexType, nodes, result, seen, containingClass);
}
else if (auto tbl = get<TableTypeVar>(ty))
fillProps(tbl->props);
else if (auto mt = get<MetatableTypeVar>(ty))
{
autocompleteProps(module, typeArena, rootTy, mt->table, indexType, nodes, result, seen);

if (FFlag::LuauSelfCallAutocompleteFix)
if (FFlag::LuauSelfCallAutocompleteFix2)
{
if (auto mtable = get<TableTypeVar>(mt->metatable))
fillMetatableProps(mtable);
Expand Down Expand Up @@ -537,7 +540,7 @@ static void autocompleteProps(const Module& module, TypeArena* typeArena, TypeId
AutocompleteEntryMap inner;
std::unordered_set<TypeId> innerSeen;

if (!FFlag::LuauSelfCallAutocompleteFix)
if (!FFlag::LuauSelfCallAutocompleteFix2)
innerSeen = seen;

if (isNil(*iter))
Expand All @@ -563,15 +566,15 @@ static void autocompleteProps(const Module& module, TypeArena* typeArena, TypeId
++iter;
}
}
else if (auto pt = get<PrimitiveTypeVar>(ty); pt && FFlag::LuauSelfCallAutocompleteFix)
else if (auto pt = get<PrimitiveTypeVar>(ty); pt && FFlag::LuauSelfCallAutocompleteFix2)
{
if (pt->metatable)
{
if (auto mtable = get<TableTypeVar>(*pt->metatable))
fillMetatableProps(mtable);
}
}
else if (FFlag::LuauSelfCallAutocompleteFix && get<StringSingleton>(get<SingletonTypeVar>(ty)))
else if (FFlag::LuauSelfCallAutocompleteFix2 && get<StringSingleton>(get<SingletonTypeVar>(ty)))
{
autocompleteProps(module, typeArena, rootTy, getSingletonTypes().stringType, indexType, nodes, result, seen);
}
Expand Down Expand Up @@ -1501,7 +1504,7 @@ static AutocompleteResult autocomplete(const SourceModule& sourceModule, const M
TypeId ty = follow(*it);
PropIndexType indexType = indexName->op == ':' ? PropIndexType::Colon : PropIndexType::Point;

if (!FFlag::LuauSelfCallAutocompleteFix && isString(ty))
if (!FFlag::LuauSelfCallAutocompleteFix2 && isString(ty))
return {autocompleteProps(*module, typeArena, typeChecker.globalScope->bindings[AstName{"string"}].typeId, indexType, finder.ancestry),
finder.ancestry};
else
Expand Down
36 changes: 2 additions & 34 deletions Analysis/src/BuiltinDefinitions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,44 +179,13 @@ void registerBuiltinTypes(TypeChecker& typeChecker)
LUAU_ASSERT(!typeChecker.globalTypes.typeVars.isFrozen());
LUAU_ASSERT(!typeChecker.globalTypes.typePacks.isFrozen());

TypeId numberType = typeChecker.numberType;
TypeId booleanType = typeChecker.booleanType;
TypeId nilType = typeChecker.nilType;

TypeArena& arena = typeChecker.globalTypes;

TypePackId oneNumberPack = arena.addTypePack({numberType});
TypePackId oneBooleanPack = arena.addTypePack({booleanType});

TypePackId numberVariadicList = arena.addTypePack(TypePackVar{VariadicTypePack{numberType}});
TypePackId listOfAtLeastOneNumber = arena.addTypePack(TypePack{{numberType}, numberVariadicList});

TypeId listOfAtLeastOneNumberToNumberType = arena.addType(FunctionTypeVar{
listOfAtLeastOneNumber,
oneNumberPack,
});

TypeId listOfAtLeastZeroNumbersToNumberType = arena.addType(FunctionTypeVar{numberVariadicList, oneNumberPack});

LoadDefinitionFileResult loadResult = Luau::loadDefinitionFile(typeChecker, typeChecker.globalScope, getBuiltinDefinitionSource(), "@luau");
LUAU_ASSERT(loadResult.success);

TypeId mathLibType = getGlobalBinding(typeChecker, "math");
if (TableTypeVar* ttv = getMutable<TableTypeVar>(mathLibType))
{
ttv->props["min"] = makeProperty(listOfAtLeastOneNumberToNumberType, "@luau/global/math.min");
ttv->props["max"] = makeProperty(listOfAtLeastOneNumberToNumberType, "@luau/global/math.max");
}

TypeId bit32LibType = getGlobalBinding(typeChecker, "bit32");
if (TableTypeVar* ttv = getMutable<TableTypeVar>(bit32LibType))
{
ttv->props["band"] = makeProperty(listOfAtLeastZeroNumbersToNumberType, "@luau/global/bit32.band");
ttv->props["bor"] = makeProperty(listOfAtLeastZeroNumbersToNumberType, "@luau/global/bit32.bor");
ttv->props["bxor"] = makeProperty(listOfAtLeastZeroNumbersToNumberType, "@luau/global/bit32.bxor");
ttv->props["btest"] = makeProperty(arena.addType(FunctionTypeVar{listOfAtLeastOneNumber, oneBooleanPack}), "@luau/global/bit32.btest");
}

TypeId genericK = arena.addType(GenericTypeVar{"K"});
TypeId genericV = arena.addType(GenericTypeVar{"V"});
TypeId mapOfKtoV = arena.addType(TableTypeVar{{}, TableIndexer(genericK, genericV), typeChecker.globalScope->level, TableState::Generic});
Expand All @@ -231,7 +200,7 @@ void registerBuiltinTypes(TypeChecker& typeChecker)

addGlobalBinding(typeChecker, "string", it->second.type, "@luau");

// next<K, V>(t: Table<K, V>, i: K | nil) -> (K, V)
// next<K, V>(t: Table<K, V>, i: K?) -> (K, V)
TypePackId nextArgsTypePack = arena.addTypePack(TypePack{{mapOfKtoV, makeOption(typeChecker, arena, genericK)}});
addGlobalBinding(typeChecker, "next",
arena.addType(FunctionTypeVar{{genericK, genericV}, {}, nextArgsTypePack, arena.addTypePack(TypePack{{genericK, genericV}})}), "@luau");
Expand All @@ -241,8 +210,7 @@ void registerBuiltinTypes(TypeChecker& typeChecker)
TypeId pairsNext = arena.addType(FunctionTypeVar{nextArgsTypePack, arena.addTypePack(TypePack{{genericK, genericV}})});
TypePackId pairsReturnTypePack = arena.addTypePack(TypePack{{pairsNext, mapOfKtoV, nilType}});

// NOTE we are missing 'i: K | nil' argument in the first return types' argument.
// pairs<K, V>(t: Table<K, V>) -> ((Table<K, V>) -> (K, V), Table<K, V>, nil)
// pairs<K, V>(t: Table<K, V>) -> ((Table<K, V>, K?) -> (K, V), Table<K, V>, nil)
addGlobalBinding(typeChecker, "pairs", arena.addType(FunctionTypeVar{{genericK, genericV}, {}, pairsArgsTypePack, pairsReturnTypePack}), "@luau");

TypeId genericMT = arena.addType(GenericTypeVar{"MT"});
Expand Down
5 changes: 0 additions & 5 deletions Analysis/src/Clone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
LUAU_FASTFLAG(DebugLuauCopyBeforeNormalizing)

LUAU_FASTINTVARIABLE(LuauTypeCloneRecursionLimit, 300)
LUAU_FASTFLAG(LuauNoMethodLocations)

namespace Luau
{
Expand Down Expand Up @@ -241,8 +240,6 @@ void TypeCloner::operator()(const TableTypeVar& t)
arg = clone(arg, dest, cloneState);

ttv->definitionModuleName = t.definitionModuleName;
if (!FFlag::LuauNoMethodLocations)
ttv->methodDefinitionLocations = t.methodDefinitionLocations;
ttv->tags = t.tags;
}

Expand Down Expand Up @@ -406,8 +403,6 @@ TypeId shallowClone(TypeId ty, TypeArena& dest, const TxnLog* log)
{
LUAU_ASSERT(!ttv->boundTo);
TableTypeVar clone = TableTypeVar{ttv->props, ttv->indexer, ttv->level, ttv->state};
if (!FFlag::LuauNoMethodLocations)
clone.methodDefinitionLocations = ttv->methodDefinitionLocations;
clone.definitionModuleName = ttv->definitionModuleName;
clone.name = ttv->name;
clone.syntheticName = ttv->syntheticName;
Expand Down
8 changes: 6 additions & 2 deletions Analysis/src/EmbeddedBuiltinDefinitions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ namespace Luau
static const std::string kBuiltinDefinitionLuaSrc = R"BUILTIN_SRC(
declare bit32: {
-- band, bor, bxor, and btest are declared in C++
band: (...number) -> number,
bor: (...number) -> number,
bxor: (...number) -> number,
btest: (number, ...number) -> boolean,
rrotate: (number, number) -> number,
lrotate: (number, number) -> number,
lshift: (number, number) -> number,
Expand Down Expand Up @@ -50,7 +53,8 @@ declare math: {
asin: (number) -> number,
atan2: (number, number) -> number,
-- min and max are declared in C++.
min: (number, ...number) -> number,
max: (number, ...number) -> number,
pi: number,
huge: number,
Expand Down
4 changes: 0 additions & 4 deletions Analysis/src/Instantiation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
#include "Luau/TxnLog.h"
#include "Luau/TypeArena.h"

LUAU_FASTFLAG(LuauNoMethodLocations)

namespace Luau
{

Expand Down Expand Up @@ -110,8 +108,6 @@ TypeId ReplaceGenerics::clean(TypeId ty)
if (const TableTypeVar* ttv = log->getMutable<TableTypeVar>(ty))
{
TableTypeVar clone = TableTypeVar{ttv->props, ttv->indexer, level, TableState::Free};
if (!FFlag::LuauNoMethodLocations)
clone.methodDefinitionLocations = ttv->methodDefinitionLocations;
clone.definitionModuleName = ttv->definitionModuleName;
return addType(std::move(clone));
}
Expand Down
35 changes: 0 additions & 35 deletions Analysis/src/Quantify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,41 +32,6 @@ struct Quantifier final : TypeVarOnceVisitor
LUAU_ASSERT(FFlag::DebugLuauDeferredConstraintResolution);
}

void cycle(TypeId) override {}
void cycle(TypePackId) override {}

bool operator()(TypeId ty, const FreeTypeVar& ftv)
{
return visit(ty, ftv);
}

template<typename T>
bool operator()(TypeId ty, const T& t)
{
return true;
}

template<typename T>
bool operator()(TypePackId, const T&)
{
return true;
}

bool operator()(TypeId ty, const ConstrainedTypeVar&)
{
return true;
}

bool operator()(TypeId ty, const TableTypeVar& ttv)
{
return visit(ty, ttv);
}

bool operator()(TypePackId tp, const FreeTypePack& ftp)
{
return visit(tp, ftp);
}

/// @return true if outer encloses inner
bool subsumes(Scope2* outer, Scope2* inner)
{
Expand Down
5 changes: 1 addition & 4 deletions Analysis/src/Scope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

#include "Luau/Scope.h"

LUAU_FASTFLAG(LuauTwoPassAliasDefinitionFix);

namespace Luau
{

Expand All @@ -19,8 +17,7 @@ Scope::Scope(const ScopePtr& parent, int subLevel)
, returnType(parent->returnType)
, level(parent->level.incr())
{
if (FFlag::LuauTwoPassAliasDefinitionFix)
level = level.incr();
level = level.incr();
level.subLevel = subLevel;
}

Expand Down

0 comments on commit b066e4c

Please sign in to comment.