Commit 5b602521 authored by jhammen's avatar jhammen
Browse files

string buffer throws exception on overflow

parent f75c708e
......@@ -198,9 +198,7 @@ LV2_Worker_Status Plugin::work(LV2_Worker_Respond_Function respond,
if (linkindex == -1) {
string mesg("Handrumr error, linked config does not exist: ");
mesg.append(link);
StringMesg errmesg(mesg.c_str(), index);
respond(handle, errmesg.size(), &errmesg);
return LV2_WORKER_ERR_UNKNOWN;
return workError(respond, handle, index, mesg);
}
}
def.filepath = path;
......@@ -225,9 +223,7 @@ LV2_Worker_Status Plugin::loadConfiguration(LV2_Worker_Respond_Function respond,
if (!ifs.is_open()) {
string mesg("Cannot open config file: ");
mesg.append(def.filepath);
StringMesg errmesg(mesg.c_str(), index);
respond(handle, errmesg.size(), &errmesg);
return LV2_WORKER_ERR_UNKNOWN;
return workError(respond, handle, index, mesg);
}
Json::Value root;
Json::CharReaderBuilder builder;
......@@ -235,9 +231,7 @@ LV2_Worker_Status Plugin::loadConfiguration(LV2_Worker_Respond_Function respond,
if (!parseFromStream(builder, ifs, &root, &errs)) {
string mesg("Handrumr JSON parse error: ");
mesg.append(errs);
StringMesg errmesg(mesg.c_str(), index);
respond(handle, errmesg.size(), &errmesg);
return LV2_WORKER_ERR_UNKNOWN;
return workError(respond, handle, index, mesg);
}
// start new config
zip *zip = nullptr;
......@@ -250,14 +244,12 @@ LV2_Worker_Status Plugin::loadConfiguration(LV2_Worker_Respond_Function respond,
float stereo = def.stereo;
if (stereo) {
if (stereo < 0 || stereo > 1.0) {
StringMesg mesg("Stereo attribute value must be in the range 0.0 to 1.0", index);
respond(handle, mesg.size(), &mesg);
return LV2_WORKER_ERR_UNKNOWN;
string mesg("Stereo attribute value must be in the range 0.0 to 1.0");
return workError(respond, handle, index, mesg);
}
if (def.channel == channelCount - 1) {
StringMesg mesg("Cannot start a stereo config on the last channel", index);
respond(handle, mesg.size(), &mesg);
return LV2_WORKER_ERR_UNKNOWN;
string mesg("Cannot start a stereo config on the last channel");
return workError(respond, handle, index, mesg);
}
static const float SQRT2_2 = 1.41421356237309 / 2; // sqrt(2)
float radians = (-1.0 + stereo * 2) * M_PI / 4;
......@@ -270,9 +262,8 @@ LV2_Worker_Status Plugin::loadConfiguration(LV2_Worker_Respond_Function respond,
int err = 0;
zip = zip_open(zipfile.c_str(), 0, &err);
if (!zip) {
StringMesg mesg("Could not open zipfile", index);
respond(handle, mesg.size(), &mesg);
return LV2_WORKER_ERR_UNKNOWN;
string mesg("Could not open zipfile");
return workError(respond, handle, index, mesg);
}
}
// instruments
......@@ -287,25 +278,20 @@ LV2_Worker_Status Plugin::loadConfiguration(LV2_Worker_Respond_Function respond,
}
break;
} catch (std::logic_error &err) {
StringMesg mesg(err.what(), index);
respond(handle, mesg.size(), &mesg);
return LV2_WORKER_ERR_UNKNOWN;
string mesg(err.what());
return workError(respond, handle, index, mesg);
}
}
}
} catch (Json::LogicError err) {
string mesg("Error parsing JSON: ");
mesg.append(err.what());
StringMesg errmesg(mesg.c_str(), index);
respond(handle, errmesg.size(), &errmesg);
return LV2_WORKER_ERR_UNKNOWN;
return workError(respond, handle, index, mesg);
}
if (!config->instrument) {
string mesg("Instrument not found in config: ");
mesg.append(def.instrument);
StringMesg errmesg(mesg.c_str(), index);
respond(handle, errmesg.size(), &errmesg);
return LV2_WORKER_ERR_UNKNOWN;
return workError(respond, handle, index, mesg);
}
if (zip) {
zip_close(zip);
......@@ -321,6 +307,14 @@ LV2_Worker_Status Plugin::loadConfiguration(LV2_Worker_Respond_Function respond,
return LV2_WORKER_SUCCESS;
}
LV2_Worker_Status Plugin::workError(LV2_Worker_Respond_Function respond,
LV2_Worker_Respond_Handle handle, uint8_t index,
std::string &mesg) {
StringMesg errmesg(index, mesg.c_str());
respond(handle, sizeof(errmesg), &errmesg);
return LV2_WORKER_ERR_UNKNOWN;
}
Instrument *Plugin::loadInstrument(Json::Value &jsonInstr, uint16_t channel, float ogaindb,
string &sampleBase, zip *zip) {
float instgain = jsonInstr.isMember("gain") ? jsonInstr["gain"].asFloat() : 0.0;
......@@ -512,12 +506,19 @@ string Plugin::channelOutOfRange(uint16_t channel) {
LV2_Worker_Status Plugin::workResponse(uint32_t size, const void *data) {
int32_t mesgtype = *((int64_t *)(data));
if (mesgtype == WKR_STRING_MESG) {
StringMesg mesg;
mesg.deserialize((const char *)data, size);
errbuffer.append("Error loading config ", 21);
errbuffer.append(mesg.index());
errbuffer.append(". ", 2);
errbuffer.append(mesg.name(), mesg.strlen());
StringMesg *mesg = static_cast<StringMesg *>((void *)data);
try {
errbuffer.append("Error loading config ", 21);
errbuffer.append(mesg->index());
errbuffer.append(". ", 2);
errbuffer.append(mesg->string(), mesg->strlen());
errbuffer.append("\n\n");
} catch (std::length_error e) {
errbuffer.clear();
errbuffer.append("Error loading config ", 21);
errbuffer.append(". Also error buffer overflow!");
}
mesg->free();
} else {
const UpdateConfigMesg *mesg = static_cast<const UpdateConfigMesg *>(data);
PluginConfig *existing = config[mesg->index()];
......@@ -757,7 +758,12 @@ void Plugin::run(uint32_t sampleCount) {
lv2_atom_forge_key(&forge, uris.config_value);
// create json
StringBuffer json;
serialize(cfgupdate.index, json, true);
try {
serialize(cfgupdate.index, json, true);
} catch (std::length_error e) {
errbuffer.clear();
errbuffer.append("Error: buffer overflow on serializing config for UI");
}
lv2_atom_forge_string(&forge, json.ptr(), json.size());
lv2_atom_forge_pop(&forge, &frame);
} else if (cfgupdate.type == CONFIG_UPDATE_GAIN) {
......@@ -810,20 +816,25 @@ void Plugin::run(uint32_t sampleCount) {
// config string is out of sync, reserialize
if (cfgdirty) {
if (pthread_mutex_trylock(&mmutex) == 0) {
StringBuffer json;
json.append("[", 1);
json.append("\n", 1);
for (int i = 0; i < configCount; i++) {
if (!config[i]) {
break;
}
if (i) {
json.append(",\n", 2);
try {
StringBuffer json;
json.append("[", 1);
json.append("\n", 1);
for (int i = 0; i < configCount; i++) {
if (!config[i]) {
break;
}
if (i) {
json.append(",\n", 2);
}
serialize(i, json, false);
}
serialize(i, json, false);
json.append("\n]", 2);
cfgstr = string(json.ptr(), json.size());
} catch (std::length_error e) {
errbuffer.clear();
errbuffer.append("Error: Buffer overflow on serializing config");
}
json.append("\n]", 2);
cfgstr = string(json.ptr(), json.size());
if (pthread_mutex_unlock(&mmutex) != 0) {
// TODO: log error
}
......
......@@ -96,34 +96,31 @@ class SamplePlay {
};
class StringBuffer {
char buffer[HD_BUFFER_SIZE];
uint32_t mend; //
char buffer[HD_BUFFER_SIZE];
public:
StringBuffer() : mend(0) {}
bool append(const char *str, uint32_t strlen) {
StringBuffer() : mend(0) { buffer[HD_BUFFER_SIZE - 1] = '\0'; }
void append(const char *str, uint32_t strlen) {
uint32_t strsize = strlen + 1;
size_t copysize = HD_BUFFER_SIZE - mend;
if (strsize <= copysize) {
strncpy(buffer + mend, str, strsize);
mend += strlen;
return true;
} else { // string larger than buffer
strncpy(buffer + mend, str, copysize);
buffer[HD_BUFFER_SIZE - 1] = '\0';
mend = HD_BUFFER_SIZE;
return false;
throw std::length_error("StringBuffer overflow");
}
}
bool append(const char *str) { return append(str, ::strlen(str)); }
bool append(uint32_t number) {
void append(const char *str) { append(str, ::strlen(str)); }
void append(uint32_t number) {
char numbuf[64];
sprintf(numbuf, "%u", number);
return append(numbuf, ::strlen(numbuf));
append(numbuf, ::strlen(numbuf));
}
bool append(float number) {
void append(float number) {
char numbuf[64];
sprintf(numbuf, "%.2f", number);
return append(numbuf, ::strlen(numbuf));
append(numbuf, ::strlen(numbuf));
}
size_t size() { return mend + 1; }
size_t strlen() { return mend; }
......@@ -176,24 +173,16 @@ class LoadMesg {
class StringMesg {
const int64_t mtype = WKR_STRING_MESG;
uint32_t mindex;
StringBuffer mname;
const uint8_t mindex;
char *mstring;
public:
StringMesg() {}
StringMesg(const char *str, uint32_t index) : mindex(index) { name(str, ::strlen(str)); }
StringMesg(uint8_t index, const char *str) : mindex(index) { mstring = strdup(str); }
void free() { ::free(mstring); }
int32_t type() { return mtype; }
bool name(const char *str, uint32_t size) { return mname.append(str, size); }
const char *name() { return mname.ptr(); }
void index(uint32_t index) { mindex = index; }
uint32_t index() { return mindex; }
size_t size() { return sizeof(mtype) + sizeof(mindex) + mname.size(); }
size_t strlen() { return mname.strlen(); }
bool deserialize(const char *buffer, uint32_t size) {
mindex = *((uint32_t *)(buffer + sizeof(mtype)));
uint32_t header = sizeof(mtype) + sizeof(mindex);
return mname.append(buffer + header, size - header);
}
uint32_t index() const { return mindex; }
char *string() { return mstring; }
size_t strlen() { return ::strlen(mstring); }
};
class UpdateGainMesg {
......@@ -307,7 +296,8 @@ class Plugin {
SampleFile *loadSampleFile(zip *zip, const string &path, float gain);
void checksamples(Instrument *layer, Instrument *orig);
void serialize(int i, StringBuffer &json, bool path);
void activate(Sample *sample);
LV2_Worker_Status workError(LV2_Worker_Respond_Function respond,
LV2_Worker_Respond_Handle handle, uint8_t index, std::string &mesg);
};
} // namespace handrumr
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment