Fix sending strings with \0 through channels

A null-char is valid part of Lua string. When such a string is sent
through the channel, its length should be stored as well to be able to
correctly reconstruct it on the other thread.

The bug was triggered with this code:

    s1 = 'a \0 b'
    print(#s1) -- 5
    ch:push(s1)
    s2 = ch:pop()
    print(#s2) -- 2
This commit is contained in:
Josip Miskovic 2022-09-21 11:53:36 +02:00 committed by Bjorn
parent 72334cc1f2
commit da9328e72c
3 changed files with 12 additions and 7 deletions

View File

@ -46,10 +46,11 @@ void luax_checkvariant(lua_State* L, int index, Variant* variant) {
variant->type = TYPE_STRING;
size_t length;
const char* string = lua_tolstring(L, index, &length);
variant->value.string = malloc(length + 1);
lovrAssert(variant->value.string, "Out of memory");
memcpy(variant->value.string, string, length);
variant->value.string[length] = '\0';
variant->value.string.pointer = malloc(length + 1);
lovrAssert(variant->value.string.pointer, "Out of memory");
memcpy(variant->value.string.pointer, string, length);
variant->value.string.pointer[length] = '\0';
variant->value.string.length = length;
break;
case LUA_TUSERDATA:
@ -80,7 +81,7 @@ int luax_pushvariant(lua_State* L, Variant* variant) {
case TYPE_NIL: lua_pushnil(L); return 1;
case TYPE_BOOLEAN: lua_pushboolean(L, variant->value.boolean); return 1;
case TYPE_NUMBER: lua_pushnumber(L, variant->value.number); return 1;
case TYPE_STRING: lua_pushstring(L, variant->value.string); return 1;
case TYPE_STRING: lua_pushlstring(L, variant->value.string.pointer, variant->value.string.length); return 1;
case TYPE_OBJECT: _luax_pushtype(L, variant->value.object.type, hash64(variant->value.object.type, strlen(variant->value.object.type)), variant->value.object.pointer); return 1;
default: return 0;
}

View File

@ -13,7 +13,7 @@ static struct {
void lovrVariantDestroy(Variant* variant) {
switch (variant->type) {
case TYPE_STRING: free(variant->value.string); return;
case TYPE_STRING: free(variant->value.string.pointer); return;
case TYPE_OBJECT: lovrRelease(variant->value.object.pointer, variant->value.object.destructor); return;
default: return;
}

View File

@ -1,5 +1,6 @@
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#pragma once
@ -33,7 +34,10 @@ typedef enum {
typedef union {
bool boolean;
double number;
char* string;
struct {
char* pointer;
size_t length;
} string;
struct {
void* pointer;
const char* type;