Bug fix in AntTweakBar TwDefineEnumFromString

Alec Jacobson

November 20, 2013

weblog/

After experiencing some odd behavior, I tracked down a bug in AntTweakBar's TwDefineEnumFromString function. The problem seems to be that the labels in the label-value pairs stored for custom enum types are stored as const char *. The original code sets these pointers to dynamically allocated std::strings via the c_str function. This is trouble because the strings are in a local scope and then the memory can be arbitrarily written over.

Without changing too much I fixed this by first copying the strings into dynamic memory. This causes a leak, but I think to fix the leak I'd have to change the implementation of the struct that stores the label-value pair and refactor.

So just change the code in TwMgr.cpp to look like:

TwType TW_CALL TwDefineEnumFromString(const char *_Name, const char *_EnumString)
{
    if (_EnumString == NULL) 
        return TwDefineEnum(_Name, NULL, 0);

    // split enumString
    stringstream EnumStream(_EnumString);
    string Label;
    vector<string> Labels;
    while( getline(EnumStream, Label, ',') ) {
        // trim Label
        size_t Start = Label.find_first_not_of(" \n\r\t");
        size_t End = Label.find_last_not_of(" \n\r\t");
        if( Start==string::npos || End==string::npos )
            Label = "";
        else
            Label = Label.substr(Start, (End-Start)+1);
        // store Label
        Labels.push_back(Label);
    }
    // create TwEnumVal array
    vector<TwEnumVal> Vals(Labels.size());
    for( int i=0; i<(int)Labels.size(); i++ )
    {
        Vals[i].Value = i;
        // CHANGE HERE:
        //Vals[i].Label = Labels[i].c_str();
        char * c_label = new char[Labels[i].length()+1];
        std::strcpy(c_label, Labels[i].c_str());
        Vals[i].Label = c_label;
    }

    return TwDefineEnum(_Name, Vals.empty() ? NULL : &(Vals[0]), (unsigned int)Vals.size());
}