Skip to content

Commit

Permalink
Support comments inside comments up to a recursion of 3 (#466)
Browse files Browse the repository at this point in the history
  • Loading branch information
lieser committed Jan 1, 2025
1 parent 4a9792e commit 67ef250
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file.
### Fixes

- Fixed potential parsing error when extracting the received time from the last Received header (#455).
- When parsing now support comments inside comments up to a recursion of 3 (#466).

### Other

Expand Down
11 changes: 8 additions & 3 deletions modules/rfcParser.mjs.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* RegExp pattern for ABNF definitions in various RFCs.
*
* Copyright (c) 2020-2023 Philippe Lieser
* Copyright (c) 2020-2025 Philippe Lieser
*
* This software is licensed under the terms of the MIT License.
*
Expand Down Expand Up @@ -43,8 +43,13 @@ export default class RfcParser {
static get FWS_op() { return `${this.FWS}?`; }
// Note: this is incomplete (obs-ctext is missing)
static get ctext() { return "[!-'*-[\\]-~]"; }
// Note: this is incomplete (comment is missing)
static get ccontent() { return `(?:${this.ctext}|${this.quoted_pair})`; }
// Note: There is a recursion in ccontent/comment, which is not supported by the RegExp in JavaScript.
// We currently unroll it to support a depth of up to 3 comments.
static get ccontent_2() { return `(?:${this.ctext}|${this.quoted_pair})`; }
static get comment_2() { return `\\((?:${this.FWS_op}${this.ccontent_2})*${this.FWS_op}\\)`; }
static get ccontent_1() { return `(?:${this.ctext}|${this.quoted_pair}|${this.comment_2})`; }
static get comment_1() { return `\\((?:${this.FWS_op}${this.ccontent_1})*${this.FWS_op}\\)`; }
static get ccontent() { return `(?:${this.ctext}|${this.quoted_pair}|${this.comment_1})`; }
static get comment() { return `\\((?:${this.FWS_op}${this.ccontent})*${this.FWS_op}\\)`; }
static get CFWS() { return `(?:(?:(?:${this.FWS_op}${this.comment})+${this.FWS_op})|${this.FWS})`; }
// Note: helper only, not part of the RFC
Expand Down
21 changes: 20 additions & 1 deletion test/unittest/arhParserSpec.mjs.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2020-2023 Philippe Lieser
* Copyright (c) 2020-2023;2025 Philippe Lieser
*
* This software is licensed under the terms of the MIT License.
*
Expand Down Expand Up @@ -167,6 +167,15 @@ describe("ARH Parser [unittest]", function () {
expect(res.resinfo[0]?.method).to.be.equal("unknown");
expect(res.resinfo[0]?.result).to.be.equal("foo");
});
it("Comments in comments", function () {
const res = ArhParser.parse(
"Authentication-Results: example.com;\r\n" +
" dkim=pass (good (comment (another)) signature(s)) header.d=example.com\r\n");
expect(res.authserv_id).to.be.equal("example.com");
expect(res.resinfo.length).to.be.equal(1);
expect(res.resinfo[0]?.method).to.be.equal("dkim");
expect(res.resinfo[0]?.result).to.be.equal("pass");
});
});
describe("Relaxed parsing", function () {
it("Trailing ;", function () {
Expand Down Expand Up @@ -235,6 +244,16 @@ describe("ARH Parser [unittest]", function () {
"Authentication-Results: example.com; dmarc=foo\r\n"
)).to.throw();
});
it("Comments with mismatching number of brackets", function () {
expect(() => ArhParser.parse(
"Authentication-Results: example.com;\r\n" +
" dkim=pass (good (comment (another))) signature(s)) header.d=example.com\r\n"
)).to.throw();
expect(() => ArhParser.parse(
"Authentication-Results: example.com;\r\n" +
" dkim=pass ((good (comment (another)) signature(s)) header.d=example.com\r\n"
)).to.throw();
});
});
describe("DKIM results", function () {
it("AUID with local part", function () {
Expand Down

0 comments on commit 67ef250

Please sign in to comment.