fix: validate float-or-percent input ranges (#15392)

This commit is contained in:
Valerii Bokhan
2026-09-12 10:59:13 -03:00
committed by GitHub
parent ccd6086787
commit 0888e331b5
25 changed files with 125 additions and 180 deletions
+1 -3
View File
@@ -4995,9 +4995,7 @@ msgstr ""
#, possible-c-format, possible-boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
#, possible-boost-format
+2 -6
View File
@@ -5429,13 +5429,9 @@ msgstr "El valor %s està fora de rang. El rang vàlid és de %d a %d."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"És %s%% or %s %s?\n"
"SÍ per %s%%.\n"
"NO per %s %s."
"És %s%% or %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5386,13 +5386,9 @@ msgstr "Hodnota %s je mimo rozsah. Platný rozsah je od %d do %d."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Je to %s%% nebo %s %s?\n"
"ANO pro %s%%,\n"
"NE pro %s %s."
"Je to %s%% nebo %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5291,13 +5291,9 @@ msgstr "Wert %s ist außerhalb des Bereichs. Der gültige Bereich liegt zwischen
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Heißt es %s%% oder %s %s?\n"
"Ja für %s%%, \n"
"Nein für %s %s."
"Heißt es %s%% oder %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+1 -3
View File
@@ -4991,9 +4991,7 @@ msgstr ""
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
#, boost-format
+2 -6
View File
@@ -5155,13 +5155,9 @@ msgstr "El valor %s está fuera de rango. El rango válido es de %d a %d."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"¿Es %s%% o %s %s?\n"
"SÍ para %s%%, \n"
"NO para %s %s."
"¿Es %s%% o %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5203,13 +5203,9 @@ msgstr "%s balioa tartetik kanpo dago. Baliozko tartea %d eta %d artekoa da."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"%s%% edo %s %s da?\n"
"BAI %s%%-(r)entzat,\n"
"EZ %s %s-(r)entzat."
"%s%% edo %s %s da?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5241,13 +5241,9 @@ msgstr "La valeur %s est hors plage. La plage valide est comprise entre %d et %d
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Est-ce %s%% ou %s %s ?\n"
"OUI pour %s%%, \n"
"NON pour %s %s."
"Est-ce %s%% ou %s %s ?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5338,13 +5338,9 @@ msgstr "%s érték tartományon kívül van. Az érvényes tartomány: %d - %d."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"%s%% vagy %s %s?\n"
"IGEN %s%%, \n"
"NEM %s %s."
"%s%% vagy %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5339,13 +5339,9 @@ msgstr "Il valore %s è fuori intervallo. L'intervallo valido è da %d a %d."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"È %s%% o %s %s?\n"
"Sì per %s%%, \n"
"NO per %s %s."
"È %s%% o %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -5
View File
@@ -5353,12 +5353,9 @@ msgstr "値%sは範囲外です。有効な範囲は%dから%dです。"
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"%s%% か、それとも %s %sですか?\n"
"%s%% の場合ははい、 %s %s はいいえ。"
"%s%% か、それとも %s %sですか?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5364,13 +5364,9 @@ msgstr "값 %s이 범위를 벗어났습니다. 유효한 범위는 %d에서 %d
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"%s%% 또는 %s %s입니까?\n"
"%s%%에 대해 예,\n"
"%s %s에 대해 아니요."
"%s%% 또는 %s %s입니까?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5325,13 +5325,9 @@ msgstr "Reikšmė %s yra už ribų. Galimas diapazonas yra nuo %d iki %d."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Ar tai %s%% ar %s %s?\n"
"TAIP %s%%, \n"
"NE %s %s."
"Ar tai %s%% ar %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5831,13 +5831,9 @@ msgstr "Waarde %s valt buiten het bereik. Het geldige bereik loopt van %d tot %d
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Is het %s%% or %s %s?\n"
"JA voor %s%%, \n"
"NEE voor %s %s."
"Is het %s%% or %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -15
View File
@@ -5452,13 +5452,9 @@ msgstr "Wartość %s jest spoza zakresu. Poprawny zakres wynosi od %d do %d."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Czy to %s%% czy %s %s?\n"
"TAK dla %s%%,\n"
"NIE dla %s %s."
"Czy to %s%% czy %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
@@ -25436,15 +25432,6 @@ msgstr ""
#~ msgid "Low-temperature filament (PLA/PETG/TPU) is loaded in the extruder. In order to avoid extruder clogging, it is not allowed to set the chamber temperature above 45℃."
#~ msgstr "W ekstruzorze jest załadowany filament o niskiej temperaturze (PLA/PETG/TPU). Aby uniknąć zatkania ekstruzora, nie wolno ustawiać temperatury komory powyżej 45℃."
#~ msgid ""
#~ "Is it %s%% or %s %s?\n"
#~ "YES for %s%%,\n"
#~ "NO for %s %s."
#~ msgstr ""
#~ "Czy to %s%% czy %s %s?\n"
#~ "TAK dla %s%%,\n"
#~ "NIE dla %s %s."
#~ msgid "Allow multiple materials on the same plate"
#~ msgstr "Pozwól na kilka filamentów na tej samej płycie"
+2 -6
View File
@@ -5169,13 +5169,9 @@ msgstr "Valor %s está fora do intervalo. O intervalo válido é de %d para %d."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"É %s%% ou %s %s?\n"
"SIM para %s%%, \n"
"NÃO para %s %s."
"É %s%% ou %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5335,13 +5335,9 @@ msgstr "Значение %s выходит за пределы допустим
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Имелось ввиду %s%%? (введено %s %s)\n"
"Да – изменить на %s%%\n"
"Нет оставить %s %s."
"Имелось ввиду %s%% или %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5905,13 +5905,9 @@ msgstr "Värdet %s ligger utanför intervallet. Giltigt intervall är från %d t
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Det är %s%% eller %s %s?\n"
"JA för %s%%, \n"
"NEJ för %s %s."
"Det är %s%% eller %s %s?"
# AI Translated
#, boost-format
+2 -6
View File
@@ -5319,13 +5319,9 @@ msgstr "ค่า %s อยู่นอกช่วง ช่วงที่ถ
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"มันคือ %s%% หรือ %s %s?\n"
"ใช่สำหรับ %s%% \n"
"ไม่ สำหรับ %s %s"
"มันคือ %s%% หรือ %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5382,13 +5382,9 @@ msgstr "Değer %s aralık dışında. Geçerli aralık %d ile %d arasındadır."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"%s%% mi yoksa %s %s mi?\n"
"%s%% için EVET,\n"
"%s %s için HAYIR."
"%s%% mi yoksa %s %s mi?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5330,13 +5330,9 @@ msgstr "Значення %s знаходиться за межами діапа
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Це %s%% або %s %s?\n"
"ТАК для %s%%, \n"
"НІ для %s %s."
"Це %s%% або %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5635,13 +5635,9 @@ msgstr "Giá trị %s nằm ngoài phạm vi. Phạm vi hợp lệ từ %d đế
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Là %s%% hay %s %s?\n"
"YES cho %s%%, \n"
"NO cho %s %s."
"Là %s%% hay %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5175,13 +5175,9 @@ msgstr "值 %s 超出了范围,有效的范围是从 %d 到 %d 。"
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"%s%%还是%s %s\n"
"是:%s%%\n"
"否:%s %s"
"%s%%还是%s %s"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5304,13 +5304,9 @@ msgstr "數值 %s 超出範圍。有效範圍是從 %d 到 %d。"
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"是 %s%% 還是 %s %s\n"
"選『是』代表 %s%%\n"
"選『否』代表 %s %s。"
"是 %s%% 還是 %s %s"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+79 -34
View File
@@ -11,6 +11,7 @@
#include "libslic3r/PrintConfig.hpp"
#include <algorithm>
#include <cmath>
#include <regex>
#include <utility>
#include <cstdint>
@@ -540,51 +541,95 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
case coStrings:
case coFloatOrPercent:
case coFloatsOrPercents: {
if ((m_opt.type == coFloatOrPercent || m_opt.type == coFloatsOrPercents) && !str.IsEmpty() && str.Last() != '%')
{
if ((m_opt.type == coFloatOrPercent || m_opt.type == coFloatsOrPercents) && !str.IsEmpty() &&
!(m_opt.nullable && str == m_na_value)) {
bool update_control = false;
wxString numeric_str = str;
double val = 0.;
const char dec_sep = is_decimal_separator_point() ? '.' : ',';
const char dec_sep_alt = dec_sep == '.' ? ',' : '.';
// Replace the first incorrect separator in decimal number.
if (str.Replace(dec_sep_alt, dec_sep, false) != 0)
set_value(str, false);
// Orca: normalize the decimal separator and optional unit before
// detecting the percentage suffix and parsing the numeric part.
update_control |= numeric_str.Replace(dec_sep_alt, dec_sep, false) != 0;
update_control |= numeric_str.Replace(" ", "", true) != 0;
const bool has_literal_unit = numeric_str.EndsWith("mm");
if (has_literal_unit) {
numeric_str.RemoveLast(2);
update_control = true;
}
bool is_percent = !numeric_str.IsEmpty() && numeric_str.Last() == '%';
if (is_percent)
numeric_str.RemoveLast();
// remove space and "mm" substring, if any exists
str.Replace(" ", "", true);
str.Replace("m", "", true);
if (!str.ToDouble(&val))
{
if ((has_literal_unit && is_percent) || !numeric_str.ToDouble(&val) || !std::isfinite(val)) {
if (!check_value) {
m_value.clear();
break;
}
show_error(m_parent, _L("Invalid numeric."));
set_value(double_to_string(val), true);
}
else if (((m_opt.sidetext.rfind("mm/s") != std::string::npos && val > m_opt.max) ||
(m_opt.sidetext.rfind("mm ") != std::string::npos && val > /*1*/m_opt.max_literal)) &&
(m_value.empty() || into_u8(str) != boost::any_cast<std::string>(m_value)))
{
if (!check_value) {
m_value.clear();
break;
numeric_str = double_to_string(std::clamp(0., double(m_opt.min), double(m_opt.max)));
is_percent = false;
update_control = true;
} else {
const bool looks_like_missing_percent = !is_percent && !has_literal_unit &&
((m_opt.sidetext.rfind("mm/s") != std::string::npos && val > m_opt.max) ||
(m_opt.sidetext.rfind("mm ") != std::string::npos && val > m_opt.max_literal));
// Orca: validate explicit percentages and literal values before
// asking whether an otherwise valid literal was meant as a percentage.
const bool out_of_range = !m_opt.is_value_valid(val);
if (out_of_range) {
if (!check_value) {
m_value.clear();
break;
}
show_error(m_parent, _L("Value is out of range."));
val = std::clamp(val, double(m_opt.min), double(m_opt.max));
// Orca: retain the inferred percent unit when clamping a
// suspicious unitless value, so 2000 becomes 100%, not 100 mm.
is_percent |= looks_like_missing_percent;
numeric_str = double_to_string(val);
update_control = true;
} else {
const bool value_changed = m_value.empty() || into_u8(str) != boost::any_cast<std::string>(m_value);
if (looks_like_missing_percent && value_changed) {
if (!check_value) {
m_value.clear();
break;
}
const std::string sidetext = m_opt.sidetext.rfind("mm/s") != std::string::npos ? "mm/s" : "mm";
const wxString stVal = numeric_str;
const wxString msg_text = from_u8((boost::format(_utf8(L("Is it %s%% or %s %s?"))) %
stVal % stVal % sidetext).str());
WarningDialog dialog(m_parent, msg_text, _L("Parameter validation") + ": " + m_opt_id, wxYES | wxNO);
dialog.SetButtonLabel(wxID_YES, stVal + _L("%"));
dialog.SetButtonLabel(wxID_NO, stVal + " " + _L(sidetext));
dialog.GetSizer()->SetSizeHints(&dialog);
dialog.Fit();
dialog.CenterOnParent();
is_percent = dialog.ShowModal() == wxID_YES;
update_control = true;
}
}
const std::string sidetext = m_opt.sidetext.rfind("mm/s") != std::string::npos ? "mm/s" : "mm";
const wxString stVal = double_to_string(val, 2);
const wxString msg_text = from_u8((boost::format(_utf8(L("Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."))) %
stVal % stVal % sidetext % stVal % stVal % sidetext)
.str());
WarningDialog dialog(m_parent, msg_text, _L("Parameter validation") + ": " + m_opt_id, wxYES | wxNO);
if ((val > 100) && dialog.ShowModal() == wxID_YES) {
set_value(from_u8((boost::format("%s%%") % stVal).str()), false /*true*/);
str += "%%";
} else
set_value(stVal, false); // it's no needed but can be helpful, when inputted value contained "," instead of "."
// Orca: also enforce the literal limit after clamping an explicit mm input.
if (!is_percent && m_opt.sidetext.rfind("mm ") != std::string::npos && val > m_opt.max_literal) {
if (!check_value) {
m_value.clear();
break;
}
if (!out_of_range)
show_error(m_parent, _L("Value is out of range."));
val = m_opt.max_literal;
numeric_str = double_to_string(val);
update_control = true;
}
}
if (update_control) {
str = numeric_str + (is_percent ? "%" : "");
set_value(str, true);
}
}
if (m_opt.opt_key == "thumbnails") {