Add some paranoid format string checking in popup slider dialogs

This commit is contained in:
Henrik Rydgård 2023-04-28 20:26:08 +02:00
parent 7698fda7e0
commit c02634c161
3 changed files with 43 additions and 17 deletions

View file

@ -42,7 +42,7 @@ void Buffer::Append(const Buffer &other) {
void Buffer::AppendValue(int value) {
char buf[16];
// This is slow.
sprintf(buf, "%i", value);
snprintf(buf, sizeof(buf), "%i", value);
Append(buf);
}

View file

@ -146,13 +146,13 @@ std::string PopupMultiChoice::ValueText() const {
PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, int defaultValue, const std::string &text, ScreenManager *screenManager, const std::string &units, LayoutParams *layoutParams)
: AbstractChoiceWithValueDisplay(text, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), defaultValue_(defaultValue), step_(1), units_(units), screenManager_(screenManager) {
fmt_ = "%i";
fmt_ = "%d";
OnClick.Handle(this, &PopupSliderChoice::HandleClick);
}
PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, int defaultValue, const std::string &text, int step, ScreenManager *screenManager, const std::string &units, LayoutParams *layoutParams)
: AbstractChoiceWithValueDisplay(text, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), defaultValue_(defaultValue), step_(step), units_(units), screenManager_(screenManager) {
fmt_ = "%i";
fmt_ = "%d";
OnClick.Handle(this, &PopupSliderChoice::HandleClick);
}
@ -191,18 +191,41 @@ EventReturn PopupSliderChoice::HandleChange(EventParams &e) {
return EVENT_DONE;
}
static bool IsValidNumberFormatString(const std::string &s) {
if (s.empty())
return false;
size_t percentCount = 0;
for (int i = 0; i < (int)s.size(); i++) {
if (s[i] == '%') {
percentCount++;
if (i < s.size() - 1) {
if (s[i] == 's')
return false;
}
}
}
return percentCount == 1;
}
std::string PopupSliderChoice::ValueText() const {
// Always good to have space for Unicode.
char temp[256];
temp[0] = '\0';
if (zeroLabel_.size() && *value_ == 0) {
strcpy(temp, zeroLabel_.c_str());
truncate_cpy(temp, zeroLabel_.c_str());
} else if (negativeLabel_.size() && *value_ < 0) {
strcpy(temp, negativeLabel_.c_str());
truncate_cpy(temp, negativeLabel_.c_str());
} else {
sprintf(temp, fmt_, *value_);
// Would normally be dangerous to have user-controlled format strings!
// However, let's check that there's only one % sign, and that it's not followed by an S.
// Also, these strings are from translations, which are kinda-fixed (though can be modified in theory).
if (IsValidNumberFormatString(fmt_)) {
snprintf(temp, sizeof(temp), fmt_.c_str(), *value_);
} else {
truncate_cpy(temp, "(translation error)");
}
}
return temp;
return std::string(temp);
}
EventReturn PopupSliderChoiceFloat::HandleClick(EventParams &e) {
@ -229,12 +252,14 @@ EventReturn PopupSliderChoiceFloat::HandleChange(EventParams &e) {
std::string PopupSliderChoiceFloat::ValueText() const {
char temp[256];
temp[0] = '\0';
if (zeroLabel_.size() && *value_ == 0.0f) {
strcpy(temp, zeroLabel_.c_str());
truncate_cpy(temp, zeroLabel_.c_str());
} else if (IsValidNumberFormatString(fmt_.c_str())) {
snprintf(temp, sizeof(temp), fmt_.c_str(), *value_);
} else {
sprintf(temp, fmt_, *value_);
snprintf(temp, sizeof(temp), "%0.2f", *value_);
}
return temp;
}
@ -282,8 +307,8 @@ EventReturn SliderPopupScreen::OnTextChange(EventParams &params) {
}
void SliderPopupScreen::UpdateTextBox() {
char temp[64];
sprintf(temp, "%d", sliderValue_);
char temp[128];
snprintf(temp, sizeof(temp), "%d", sliderValue_);
edit_->SetText(temp);
}
@ -295,6 +320,7 @@ void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
sliderValue_ = *value_;
if (disabled_ && sliderValue_ < 0)
sliderValue_ = 0;
LinearLayout *vert = parent->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(UI::Margins(10, 10))));
slider_ = new Slider(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 10)));
slider_->OnChange.Handle(this, &SliderPopupScreen::OnSliderChange);
@ -417,8 +443,8 @@ EventReturn SliderFloatPopupScreen::OnSliderChange(EventParams &params) {
}
void SliderFloatPopupScreen::UpdateTextBox() {
char temp[64];
sprintf(temp, "%0.3f", sliderValue_);
char temp[128];
snprintf(temp, sizeof(temp), "%0.3f", sliderValue_);
edit_->SetText(temp);
}

View file

@ -309,7 +309,7 @@ private:
int maxValue_;
int defaultValue_;
int step_;
const char *fmt_;
std::string fmt_;
std::string zeroLabel_;
std::string negativeLabel_;
std::string units_;
@ -348,7 +348,7 @@ private:
float maxValue_;
float defaultValue_;
float step_;
const char *fmt_;
std::string fmt_;
std::string zeroLabel_;
std::string units_;
ScreenManager *screenManager_;