mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-02 05:12:02 +00:00
[client] overlay: fix unsafe ImGui string handling
This commit is contained in:
@@ -28,10 +28,11 @@
|
|||||||
|
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/appstrings.h"
|
#include "common/appstrings.h"
|
||||||
|
#include "common/stringutils.h"
|
||||||
|
|
||||||
typedef struct ConfigCallback
|
typedef struct ConfigCallback
|
||||||
{
|
{
|
||||||
const char * title;
|
char * title;
|
||||||
void * udata;
|
void * udata;
|
||||||
void (*callback)(void * udata, int * id);
|
void (*callback)(void * udata, int * id);
|
||||||
}
|
}
|
||||||
@@ -61,7 +62,10 @@ static void config_freeList(struct ll * list)
|
|||||||
{
|
{
|
||||||
ConfigCallback * cb;
|
ConfigCallback * cb;
|
||||||
while(ll_shift(list, (void **)&cb))
|
while(ll_shift(list, (void **)&cb))
|
||||||
|
{
|
||||||
|
free(cb->title);
|
||||||
free(cb);
|
free(cb);
|
||||||
|
}
|
||||||
ll_free(list);
|
ll_free(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,9 +82,9 @@ static void config_renderLGTab(void)
|
|||||||
if (igCollapsingHeader_BoolPtr("Donations", NULL,
|
if (igCollapsingHeader_BoolPtr("Donations", NULL,
|
||||||
ImGuiTreeNodeFlags_DefaultOpen))
|
ImGuiTreeNodeFlags_DefaultOpen))
|
||||||
{
|
{
|
||||||
igTextWrapped(LG_DONATION_STR);
|
igTextWrapped("%s", LG_DONATION_STR);
|
||||||
|
|
||||||
igBeginTable("split", 2, 0, (ImVec2){}, 0.0f);
|
igBeginTable("donations_split", 2, 0, (ImVec2){}, 0.0f);
|
||||||
igTableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, fontSize, 0);
|
igTableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, fontSize, 0);
|
||||||
igTableNextColumn();
|
igTableNextColumn();
|
||||||
igBulletText("");
|
igBulletText("");
|
||||||
@@ -93,12 +97,12 @@ static void config_renderLGTab(void)
|
|||||||
if (igCollapsingHeader_BoolPtr("Help & Support", NULL,
|
if (igCollapsingHeader_BoolPtr("Help & Support", NULL,
|
||||||
ImGuiTreeNodeFlags_DefaultOpen))
|
ImGuiTreeNodeFlags_DefaultOpen))
|
||||||
{
|
{
|
||||||
igBeginTable("split", 2, 0, (ImVec2){}, 0.0f);
|
igBeginTable("help_support_split", 2, 0, (ImVec2){}, 0.0f);
|
||||||
igTableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, fontSize * 9.0f, 0);
|
igTableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, fontSize * 9.0f, 0);
|
||||||
for(const StringPair * help = LG_HELP_LINKS; help->name; ++help)
|
for(const StringPair * help = LG_HELP_LINKS; help->name; ++help)
|
||||||
{
|
{
|
||||||
igTableNextColumn();
|
igTableNextColumn();
|
||||||
igBulletText(help->name);
|
igBulletText("%s", help->name);
|
||||||
igTableNextColumn();
|
igTableNextColumn();
|
||||||
overlayTextMaybeURL(help->value, true);
|
overlayTextMaybeURL(help->value, true);
|
||||||
}
|
}
|
||||||
@@ -113,7 +117,7 @@ static void config_renderLGTab(void)
|
|||||||
if (igTreeNode_Str(member->name))
|
if (igTreeNode_Str(member->name))
|
||||||
{
|
{
|
||||||
igSpacing();
|
igSpacing();
|
||||||
igTextWrapped(member->blurb);
|
igTextWrapped("%s", member->blurb);
|
||||||
if (member->donate[0].name)
|
if (member->donate[0].name)
|
||||||
{
|
{
|
||||||
igSeparator();
|
igSeparator();
|
||||||
@@ -122,13 +126,13 @@ static void config_renderLGTab(void)
|
|||||||
"do so directly via the following platform%s:",
|
"do so directly via the following platform%s:",
|
||||||
member->donate[1].name ? "s" : "");
|
member->donate[1].name ? "s" : "");
|
||||||
|
|
||||||
igBeginTable("split", 2, 0, (ImVec2){}, 0.0f);
|
igBeginTable("member_donations_split", 2, 0, (ImVec2){}, 0.0f);
|
||||||
igTableSetupColumn("", ImGuiTableColumnFlags_WidthFixed,
|
igTableSetupColumn("", ImGuiTableColumnFlags_WidthFixed,
|
||||||
fontSize * 10.0f, 0);
|
fontSize * 10.0f, 0);
|
||||||
for(const StringPair * donate = member->donate; donate->name; ++donate)
|
for(const StringPair * donate = member->donate; donate->name; ++donate)
|
||||||
{
|
{
|
||||||
igTableNextColumn();
|
igTableNextColumn();
|
||||||
igBulletText(donate->name);
|
igBulletText("%s", donate->name);
|
||||||
igTableNextColumn();
|
igTableNextColumn();
|
||||||
overlayTextMaybeURL(donate->value, false);
|
overlayTextMaybeURL(donate->value, false);
|
||||||
}
|
}
|
||||||
@@ -143,11 +147,11 @@ static void config_renderLGTab(void)
|
|||||||
|
|
||||||
static void config_renderLicenseTab(void)
|
static void config_renderLicenseTab(void)
|
||||||
{
|
{
|
||||||
igText(LG_COPYRIGHT_STR);
|
igTextUnformatted(LG_COPYRIGHT_STR, NULL);
|
||||||
overlayTextURL(LG_WEBSITE_URL, NULL);
|
overlayTextURL(LG_WEBSITE_URL, NULL);
|
||||||
igText(LG_VERSION_STR);
|
igTextUnformatted(LG_VERSION_STR, NULL);
|
||||||
igSeparator();
|
igSeparator();
|
||||||
igTextWrapped(LG_LICENSE_STR);
|
igTextWrapped("%s", LG_LICENSE_STR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int config_render(void * udata, bool interactive, struct Rect * windowRects,
|
static int config_render(void * udata, bool interactive, struct Rect * windowRects,
|
||||||
@@ -246,6 +250,12 @@ struct LG_OverlayOps LGOverlayConfig =
|
|||||||
static void config_addToList(struct ll * list, const char * title,
|
static void config_addToList(struct ll * list, const char * title,
|
||||||
void(*callback)(void * udata, int * id), void * udata)
|
void(*callback)(void * udata, int * id), void * udata)
|
||||||
{
|
{
|
||||||
|
if (!title || !*title)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("configuration title must not be empty");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ConfigCallback * cb = calloc(1, sizeof(*cb));
|
ConfigCallback * cb = calloc(1, sizeof(*cb));
|
||||||
if (!cb)
|
if (!cb)
|
||||||
{
|
{
|
||||||
@@ -253,7 +263,14 @@ static void config_addToList(struct ll * list, const char * title,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cb->title = title;
|
cb->title = lg_strdup(title);
|
||||||
|
if (!cb->title)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("failed to allocate ram");
|
||||||
|
free(cb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cb->udata = udata;
|
cb->udata = udata;
|
||||||
cb->callback = callback;
|
cb->callback = callback;
|
||||||
ll_push(list, cb);
|
ll_push(list, cb);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "../main.h"
|
#include "../main.h"
|
||||||
|
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
|
#include "common/stringutils.h"
|
||||||
#include "overlay_utils.h"
|
#include "overlay_utils.h"
|
||||||
|
|
||||||
struct GraphState
|
struct GraphState
|
||||||
@@ -36,7 +37,7 @@ static struct GraphState gs = {0};
|
|||||||
|
|
||||||
struct OverlayGraph
|
struct OverlayGraph
|
||||||
{
|
{
|
||||||
const char * name;
|
char * name;
|
||||||
RingBuffer buffer;
|
RingBuffer buffer;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
float min;
|
float min;
|
||||||
@@ -50,7 +51,7 @@ static void configCallback(void * udata, int * id)
|
|||||||
igCheckbox("Show timing graphs", &gs.show);
|
igCheckbox("Show timing graphs", &gs.show);
|
||||||
igSeparator();
|
igSeparator();
|
||||||
|
|
||||||
igBeginTable("split", 2, 0, (ImVec2){}, 0);
|
igBeginTable("graphs_split", 2, 0, (ImVec2){}, 0);
|
||||||
|
|
||||||
GraphHandle graph;
|
GraphHandle graph;
|
||||||
ll_lock(gs.graphs);
|
ll_lock(gs.graphs);
|
||||||
@@ -89,7 +90,10 @@ static void graphs_free(void * udata)
|
|||||||
{
|
{
|
||||||
struct OverlayGraph * graph;
|
struct OverlayGraph * graph;
|
||||||
while(ll_shift(gs.graphs, (void **)&graph))
|
while(ll_shift(gs.graphs, (void **)&graph))
|
||||||
|
{
|
||||||
|
free(graph->name);
|
||||||
free(graph);
|
free(graph);
|
||||||
|
}
|
||||||
ll_free(gs.graphs);
|
ll_free(gs.graphs);
|
||||||
gs.graphs = NULL;
|
gs.graphs = NULL;
|
||||||
}
|
}
|
||||||
@@ -231,6 +235,12 @@ struct LG_OverlayOps LGOverlayGraphs =
|
|||||||
GraphHandle overlayGraph_register(const char * name, RingBuffer buffer,
|
GraphHandle overlayGraph_register(const char * name, RingBuffer buffer,
|
||||||
float min, float max, GraphFormatFn formatFn)
|
float min, float max, GraphFormatFn formatFn)
|
||||||
{
|
{
|
||||||
|
if (!name || !*name)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("graph name must not be empty");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
struct OverlayGraph * graph = malloc(sizeof(*graph));
|
struct OverlayGraph * graph = malloc(sizeof(*graph));
|
||||||
if (!graph)
|
if (!graph)
|
||||||
{
|
{
|
||||||
@@ -238,7 +248,14 @@ GraphHandle overlayGraph_register(const char * name, RingBuffer buffer,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
graph->name = name;
|
graph->name = lg_strdup(name);
|
||||||
|
if (!graph->name)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("out of memory");
|
||||||
|
free(graph);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
graph->buffer = buffer;
|
graph->buffer = buffer;
|
||||||
graph->enabled = true;
|
graph->enabled = true;
|
||||||
graph->min = min;
|
graph->min = min;
|
||||||
@@ -250,10 +267,11 @@ GraphHandle overlayGraph_register(const char * name, RingBuffer buffer,
|
|||||||
|
|
||||||
void overlayGraph_unregister(GraphHandle handle)
|
void overlayGraph_unregister(GraphHandle handle)
|
||||||
{
|
{
|
||||||
if (!gs.graphs)
|
if (!gs.graphs || !handle)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ll_removeData(gs.graphs, handle);
|
ll_removeData(gs.graphs, handle);
|
||||||
|
free(handle->name);
|
||||||
free(handle);
|
free(handle);
|
||||||
|
|
||||||
if (gs.show)
|
if (gs.show)
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ static int help_render(void * udata, bool interactive, struct Rect * windowRects
|
|||||||
else
|
else
|
||||||
igText("%s+%c", escapeName, handle->charcode);
|
igText("%s+%c", escapeName, handle->charcode);
|
||||||
igTableNextColumn();
|
igTableNextColumn();
|
||||||
igText(handle->description);
|
igTextUnformatted(handle->description, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
igEndTable();
|
igEndTable();
|
||||||
|
|||||||
@@ -205,35 +205,56 @@ MsgBoxHandle overlayMsg_show(
|
|||||||
const char * caption, MsgBoxConfirmCallback confirm, void * opaque,
|
const char * caption, MsgBoxConfirmCallback confirm, void * opaque,
|
||||||
const char * fmt, va_list args)
|
const char * fmt, va_list args)
|
||||||
{
|
{
|
||||||
struct Msg * msg = malloc(sizeof(*msg));
|
struct Msg * msg = calloc(1, sizeof(*msg));
|
||||||
if (!msg)
|
if (!msg)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("out of memory");
|
DEBUG_ERROR("out of memory");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg->caption = strdup(caption);
|
msg->caption = lg_strdup(caption && *caption ? caption : "Message");
|
||||||
|
if (!msg->caption)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("out of memory");
|
||||||
|
free(msg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
msg->lines = stringlist_new(false);
|
msg->lines = stringlist_new(false);
|
||||||
|
if (!msg->lines)
|
||||||
|
{
|
||||||
|
free(msg->caption);
|
||||||
|
free(msg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
msg->confirm = confirm;
|
msg->confirm = confirm;
|
||||||
msg->opaque = opaque;
|
msg->opaque = opaque;
|
||||||
valloc_sprintf(&msg->message, fmt, args);
|
if (valloc_sprintf(&msg->message, fmt ? fmt : "", args) < 0)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("failed to format message");
|
||||||
|
freeMsg(msg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
char * token = msg->message;
|
char * token = msg->message;
|
||||||
char * rest = msg->message;
|
for(char * rest = msg->message; ; ++rest)
|
||||||
do
|
|
||||||
{
|
{
|
||||||
if (*rest == '\n')
|
if (*rest == '\n')
|
||||||
{
|
{
|
||||||
*rest = '\0';
|
*rest = '\0';
|
||||||
stringlist_push(msg->lines, token);
|
stringlist_push(msg->lines, token);
|
||||||
token = rest + 1;
|
token = rest + 1;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
++rest;
|
|
||||||
}
|
|
||||||
while(*rest != '\0');
|
|
||||||
|
|
||||||
|
if (*rest == '\0')
|
||||||
|
{
|
||||||
if (*token)
|
if (*token)
|
||||||
stringlist_push(msg->lines, token);
|
stringlist_push(msg->lines, token);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ll_push(l_msg.messages, msg);
|
ll_push(l_msg.messages, msg);
|
||||||
app_invalidateOverlay(false);
|
app_invalidateOverlay(false);
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ static void overlayAddUnderline(ImU32 color)
|
|||||||
|
|
||||||
void overlayTextURL(const char * url, const char * text)
|
void overlayTextURL(const char * url, const char * text)
|
||||||
{
|
{
|
||||||
igText(text ? text : url);
|
igTextUnformatted(text ? text : url, NULL);
|
||||||
|
|
||||||
if (igIsItemHovered(ImGuiHoveredFlags_None))
|
if (igIsItemHovered(ImGuiHoveredFlags_None))
|
||||||
{
|
{
|
||||||
@@ -87,9 +87,9 @@ void overlayTextMaybeURL(const char * text, bool wrapped)
|
|||||||
if (strncmp(text, "https://", 8) == 0)
|
if (strncmp(text, "https://", 8) == 0)
|
||||||
overlayTextURL(text, NULL);
|
overlayTextURL(text, NULL);
|
||||||
else if (wrapped)
|
else if (wrapped)
|
||||||
igTextWrapped(text);
|
igTextWrapped("%s", text);
|
||||||
else
|
else
|
||||||
igText(text);
|
igTextUnformatted(text, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool overlayLoadSVG(const char * data, unsigned int size, OverlayImage * image,
|
bool overlayLoadSVG(const char * data, unsigned int size, OverlayImage * image,
|
||||||
|
|||||||
Reference in New Issue
Block a user