Reject octave formats misread by the installed buzzer parser

This commit is contained in:
mikecarper committed 2026-09-30 04:00:04 -07:00
1 parent c76278c1c7
commit 528257705d
3 files changed
+13 -5

No files matched your search

+8 -3
View File
@@ -79,19 +79,24 @@ inline bool soundDuration(const char* p,uint32_t& total) {
while(*p && *p!=':') { if(!((*p>='a'&&*p<='z')||(*p>='A'&&*p<='Z')||(*p>='0'&&*p<='9')||*p=='_')||++name>12) return false; ++p; }
if(!name||*p++!=':'||strncmp(p,"d=",2)) return false;
p+=2; uint32_t d,o,b;
if(!number(p,d,32)||!durationDenominator(d)||*p++!=','||strncmp(p,"o=",2)) return false;
if(*p=='0'||!number(p,d,32)||!durationDenominator(d)||*p++!=','||strncmp(p,"o=",2)) return false;
p+=2;
if(!number(p,o,7)||o<4||*p++!=','||strncmp(p,"b=",2)) return false;
// The installed driver consumes exactly one octave digit, unlike duration
// and BPM. Accepting c04 would send octave 0 into its pitch-table index.
if(*p<'4'||*p>'7')return false;
o=*p++-'0';
if(*p++!=','||strncmp(p,"b=",2)) return false;
p+=2;
if(!number(p,b,900)||b<25||*p++!=':'||!*p) return false;
do {
uint32_t nd=d,no=o;
if(*p=='0')return false;
if(*p>='0'&&*p<='9' && (!number(p,nd,32)||!durationDenominator(nd))) return false;
char note=*p++;
if((note<'a'||note>'g')&&note!='p') return false;
if(*p=='#') { if(note!='a'&&note!='c'&&note!='d'&&note!='f'&&note!='g') return false; ++p; }
bool dot=*p=='.'; if(dot) ++p;
if(*p>='0'&&*p<='9' && (!number(p,no,7)||no<4)) return false;
if(*p>='0'&&*p<='9') { no=*p++-'0';if(no<4||no>7)return false; }
if(*p=='.') { if(dot) return false; dot=true; ++p; }
uint32_t ms=(60000/b)*4/nd; if(dot) ms+=ms/2;
total+=ms;
@@ -43,7 +43,9 @@ TEST(NotificationParsing, ValidatesTheActualBuzzerTableAndRtttlSyntax) {
for(auto text:{"abc","x:d=8,o=3,b=120:c","x:d=8,o=5,b=0:c","x:d=8,o=8,b=120:c",
"x:d=3,o=5,b=120:c","x:d=8,o=5,b=120:b#7","x:d=8,o=5,b=120:c,",
"x:d=8,o=5,b=120:c..","x:d=8,o=5,b=120:c8","x:d=8,o=5,b=120:p#",
"x:d=8,o=5,b=120:c+","x:d=8,o=5,b=120:c, d"})EXPECT_FALSE(soundDuration(text,ms))<<text;
"x:d=8,o=5,b=120:c+","x:d=8,o=5,b=120:c, d","x:d=8,o=04,b=120:c",
"x:d=8,o=5,b=120:c04","x:d=8,o=5,b=120:c007","x:d=08,o=5,b=120:c",
"x:d=8,o=5,b=120:04c"})EXPECT_FALSE(soundDuration(text,ms))<<text;
}
TEST_F(Notifications, ExecutesExactBoundaryPulsesAndReturnsOutputsOff) {
EXPECT_EQ("OK",cmd("set notify.led all 50,300,40,20,500"));
+2 -1
View File
@@ -9,7 +9,8 @@ for (const bad of ["0", "50,", "50,,20", "60001", "-5", "50 20", "1,1,1,1,1,1,1,
assert.throws(() => builder.pulse(bad));
assert.equal(builder.melody("vip:d=8,o=5,b=120:c,c#,16p,4g.6").length, 4);
for (const bad of ["abc", "x:d=8,o=3,b=120:c", "x:d=8,o=5,b=0:c", "x:d=3,o=5,b=120:c",
"x:d=8,o=5,b=120:b#7", "x:d=8,o=5,b=120:c,", "x:d=8,o=5,b=120:c..", "x:d=8,o=5,b=120:p#"])
"x:d=8,o=5,b=120:b#7", "x:d=8,o=5,b=120:c,", "x:d=8,o=5,b=120:c..", "x:d=8,o=5,b=120:p#",
"x:d=8,o=04,b=120:c", "x:d=8,o=5,b=120:c04", "x:d=8,o=5,b=120:c007", "x:d=08,o=5,b=120:c", "x:d=8,o=5,b=120:04c"])
assert.throws(() => builder.melody(bad));
for (const config of Object.values(builder.EXAMPLES)) {
const complete = {...config, id: config.kind === "contact" ? "01".repeat(32) : config.id};