Error when invalid setting names are used in the tables passed to love.graphics.newCanvas and newImage. See issue #1312.

This commit is contained in:
Alex Szpakowski
2017-12-28 23:16:51 -04:00
parent 1f52abf619
commit dd59803ad3
9 changed files with 143 additions and 31 deletions
+22
View File
@@ -474,6 +474,28 @@ extern "C" { // Also called from luasocket
int luax_enumerror(lua_State *L, const char *enumName, const char *value);
int luax_enumerror(lua_State *L, const char *enumName, const std::vector<std::string> &values, const char *value);
template <typename T>
void luax_checktablefields(lua_State *L, int idx, const char *enumName, bool (*getConstant)(const char *, T &))
{
luaL_checktype(L, idx, LUA_TTABLE);
// We want to error for invalid / misspelled fields in the table.
lua_pushnil(L);
while (lua_next(L, idx))
{
if (lua_type(L, -2) != LUA_TSTRING)
luax_typerror(L, -2, "string");
const char *key = luaL_checkstring(L, -2);
T constantvalue;
if (!getConstant(key, constantvalue))
luax_enumerror(L, enumName, key);
lua_pop(L, 1);
}
}
/**
* Calls luax_objlen/lua_rawlen depending on version
**/
+36
View File
@@ -195,6 +195,28 @@ std::vector<std::string> Canvas::getConstants(MipmapMode)
return mipmapModes.getNames();
}
bool Canvas::getConstant(const char *in, SettingType &out)
{
return settingTypes.find(in, out);
}
bool Canvas::getConstant(SettingType in, const char *&out)
{
return settingTypes.find(in, out);
}
const char *Canvas::getConstant(SettingType in)
{
const char *name = nullptr;
getConstant(in, name);
return name;
}
std::vector<std::string> Canvas::getConstants(SettingType)
{
return settingTypes.getNames();
}
StringMap<Canvas::MipmapMode, Canvas::MIPMAPS_MAX_ENUM>::Entry Canvas::mipmapEntries[] =
{
{ "none", MIPMAPS_NONE },
@@ -204,6 +226,20 @@ StringMap<Canvas::MipmapMode, Canvas::MIPMAPS_MAX_ENUM>::Entry Canvas::mipmapEnt
StringMap<Canvas::MipmapMode, Canvas::MIPMAPS_MAX_ENUM> Canvas::mipmapModes(Canvas::mipmapEntries, sizeof(Canvas::mipmapEntries));
StringMap<Canvas::SettingType, Canvas::SETTING_MAX_ENUM>::Entry Canvas::settingTypeEntries[] =
{
// Width / height / layers are currently omittted because they're separate
// arguments to newCanvas in the wrapper code.
{ "mipmaps", SETTING_MIPMAPS },
{ "format", SETTING_FORMAT },
{ "type", SETTING_TYPE },
{ "dpiscale", SETTING_DPI_SCALE },
{ "msaa", SETTING_MSAA },
{ "readable", SETTING_READABLE },
};
StringMap<Canvas::SettingType, Canvas::SETTING_MAX_ENUM> Canvas::settingTypes(Canvas::settingTypeEntries, sizeof(Canvas::settingTypeEntries));
} // graphics
} // love
+22
View File
@@ -47,6 +47,20 @@ public:
MIPMAPS_MAX_ENUM
};
enum SettingType
{
SETTING_WIDTH,
SETTING_HEIGHT,
SETTING_LAYERS,
SETTING_MIPMAPS,
SETTING_FORMAT,
SETTING_TYPE,
SETTING_DPI_SCALE,
SETTING_MSAA,
SETTING_READABLE,
SETTING_MAX_ENUM
};
struct Settings
{
int width = 1;
@@ -81,6 +95,11 @@ public:
static bool getConstant(MipmapMode in, const char *&out);
static std::vector<std::string> getConstants(MipmapMode);
static bool getConstant(const char *in, SettingType &out);
static bool getConstant(SettingType in, const char *&out);
static const char *getConstant(SettingType in);
static std::vector<std::string> getConstants(SettingType);
protected:
Settings settings;
@@ -89,6 +108,9 @@ private:
static StringMap<MipmapMode, MIPMAPS_MAX_ENUM>::Entry mipmapEntries[];
static StringMap<MipmapMode, MIPMAPS_MAX_ENUM> mipmapModes;
static StringMap<SettingType, SETTING_MAX_ENUM>::Entry settingTypeEntries[];
static StringMap<SettingType, SETTING_MAX_ENUM> settingTypes;
}; // Canvas
+3
View File
@@ -129,6 +129,9 @@ Graphics::Graphics()
pixelScaleStack.reserve(16);
pixelScaleStack.push_back(1);
states.reserve(10);
states.push_back(DisplayState());
if (!Shader::initialize())
throw love::Exception("Shader support failed to initialize!");
}
+31
View File
@@ -340,5 +340,36 @@ Image::MipmapsType Image::Slices::validate() const
return MIPMAPS_NONE;
}
bool Image::getConstant(const char *in, SettingType &out)
{
return settingTypes.find(in, out);
}
bool Image::getConstant(SettingType in, const char *&out)
{
return settingTypes.find(in, out);
}
const char *Image::getConstant(SettingType in)
{
const char *name = nullptr;
getConstant(in, name);
return name;
}
std::vector<std::string> Image::getConstants(SettingType)
{
return settingTypes.getNames();
}
StringMap<Image::SettingType, Image::SETTING_MAX_ENUM>::Entry Image::settingTypeEntries[] =
{
{ "mipmaps", SETTING_MIPMAPS },
{ "linear", SETTING_LINEAR },
{ "dpiscale", SETTING_DPI_SCALE },
};
StringMap<Image::SettingType, Image::SETTING_MAX_ENUM> Image::settingTypes(Image::settingTypeEntries, sizeof(Image::settingTypeEntries));
} // graphics
} // love
+16
View File
@@ -46,6 +46,14 @@ public:
MIPMAPS_GENERATED,
};
enum SettingType
{
SETTING_MIPMAPS,
SETTING_LINEAR,
SETTING_DPI_SCALE,
SETTING_MAX_ENUM
};
struct Settings
{
bool mipmaps = false;
@@ -94,6 +102,11 @@ public:
static int imageCount;
static bool getConstant(const char *in, SettingType &out);
static bool getConstant(SettingType in, const char *&out);
static const char *getConstant(SettingType in);
static std::vector<std::string> getConstants(SettingType);
protected:
Image(const Slices &data, const Settings &settings);
@@ -122,6 +135,9 @@ private:
void init(PixelFormat fmt, int w, int h, const Settings &settings);
static StringMap<SettingType, SETTING_MAX_ENUM>::Entry settingTypeEntries[];
static StringMap<SettingType, SETTING_MAX_ENUM> settingTypes;
}; // Image
} // graphics
-3
View File
@@ -60,9 +60,6 @@ Graphics::Graphics()
{
gl = OpenGL();
states.reserve(10);
states.push_back(DisplayState());
auto window = getInstance<love::window::Window>(M_WINDOW);
if (window != nullptr)
+12 -11
View File
@@ -701,10 +701,11 @@ static Image::Settings w__optImageSettings(lua_State *L, int idx, const Image::S
if (!lua_isnoneornil(L, idx))
{
luaL_checktype(L, idx, LUA_TTABLE);
settings.mipmaps = luax_boolflag(L, idx, "mipmaps", s.mipmaps);
settings.linear = luax_boolflag(L, idx, "linear", s.linear);
settings.dpiScale = (float) luax_numberflag(L, idx, "dpiscale", s.dpiScale);
luax_checktablefields<Image::SettingType>(L, idx, "image setting name", Image::getConstant);
settings.mipmaps = luax_boolflag(L, idx, Image::getConstant(Image::SETTING_MIPMAPS), s.mipmaps);
settings.linear = luax_boolflag(L, idx, Image::getConstant(Image::SETTING_LINEAR), s.linear);
settings.dpiScale = (float) luax_numberflag(L, idx, Image::getConstant(Image::SETTING_DPI_SCALE), s.dpiScale);
}
return settings;
@@ -1186,12 +1187,12 @@ int w_newCanvas(lua_State *L)
if (!lua_isnoneornil(L, startidx))
{
luaL_checktype(L, startidx, LUA_TTABLE);
luax_checktablefields<Canvas::SettingType>(L, startidx, "canvas setting name", Canvas::getConstant);
settings.dpiScale = (float) luax_numberflag(L, startidx, "dpiscale", settings.dpiScale);
settings.msaa = luax_intflag(L, startidx, "msaa", settings.msaa);
settings.dpiScale = (float) luax_numberflag(L, startidx, Canvas::getConstant(Canvas::SETTING_DPI_SCALE), settings.dpiScale);
settings.msaa = luax_intflag(L, startidx, Canvas::getConstant(Canvas::SETTING_MSAA), settings.msaa);
lua_getfield(L, startidx, "format");
lua_getfield(L, startidx, Canvas::getConstant(Canvas::SETTING_FORMAT));
if (!lua_isnoneornil(L, -1))
{
const char *str = luaL_checkstring(L, -1);
@@ -1200,7 +1201,7 @@ int w_newCanvas(lua_State *L)
}
lua_pop(L, 1);
lua_getfield(L, startidx, "type");
lua_getfield(L, startidx, Canvas::getConstant(Canvas::SETTING_TYPE));
if (!lua_isnoneornil(L, -1))
{
const char *str = luaL_checkstring(L, -1);
@@ -1209,7 +1210,7 @@ int w_newCanvas(lua_State *L)
}
lua_pop(L, 1);
lua_getfield(L, startidx, "readable");
lua_getfield(L, startidx, Canvas::getConstant(Canvas::SETTING_READABLE));
if (!lua_isnoneornil(L, -1))
{
settings.readable.hasValue = true;
@@ -1217,7 +1218,7 @@ int w_newCanvas(lua_State *L)
}
lua_pop(L, 1);
lua_getfield(L, startidx, "mipmaps");
lua_getfield(L, startidx, Canvas::getConstant(Canvas::SETTING_MIPMAPS));
if (!lua_isnoneornil(L, -1))
{
const char *str = luaL_checkstring(L, -1);
+1 -17
View File
@@ -54,23 +54,7 @@ static const char *settingName(Window::Setting setting)
static int readWindowSettings(lua_State *L, int idx, WindowSettings &settings)
{
luaL_checktype(L, idx, LUA_TTABLE);
// We want to error for invalid / misspelled window attributes.
lua_pushnil(L);
while (lua_next(L, idx))
{
if (lua_type(L, -2) != LUA_TSTRING)
return luax_typerror(L, -2, "string");
const char *key = luaL_checkstring(L, -2);
Window::Setting setting;
if (!Window::getConstant(key, setting))
return luax_enumerror(L, "window setting", key);
lua_pop(L, 1);
}
luax_checktablefields<Window::Setting>(L, idx, "window setting", Window::getConstant);
lua_getfield(L, idx, settingName(Window::SETTING_FULLSCREEN_TYPE));
if (!lua_isnoneornil(L, -1))