Skip to content

Commit 4abff41

Browse files
committed
Various BugFixes
Fixed the deletion of all previous tokens when there is a multiline comment within a description delimited by quotation marks. Removed RESERVED from keyword list as it is not necessary there. S19 Parser fixed when there is a malformed entry that specifies more databytes than acutally exist which would previously cause an out of bounds error.
1 parent 321d909 commit 4abff41

File tree

10 files changed

+96
-45
lines changed

10 files changed

+96
-45
lines changed

a2l/a2l.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,16 @@ var (
2121
numProc = runtime.NumCPU() * 2
2222
)
2323

24-
//A2L is the main struct returned by the a2l package.
25-
//it contains all datatypes parsed from the .a2l file
24+
// A2L is the main struct returned by the a2l package.
25+
// it contains all datatypes parsed from the .a2l file
2626
type A2L struct {
2727
Asap2Version asap2Version
2828
A2mlVersion a2mlVersion
2929
Project Project
3030
}
3131

32-
//ParseFromFile is the main exported function to be called from a2l package.
33-
//it takes an .a2l file and parses it
32+
// ParseFromFile is the main exported function to be called from a2l package.
33+
// it takes an .a2l file and parses it
3434
func ParseFromFile(filepath string) (A2L, error) {
3535
var err error
3636
var text string
@@ -64,8 +64,8 @@ func ParseFromFile(filepath string) (A2L, error) {
6464
return a, nil
6565
}
6666

67-
//parseA2l handles the parsing of the a2l struct.
68-
//as opposed to ParseFromFile which also handles creation of the tokenizer and file reading, etc.
67+
// parseA2l handles the parsing of the a2l struct.
68+
// as opposed to ParseFromFile which also handles creation of the tokenizer and file reading, etc.
6969
func parseA2l(tok *tokenGenerator) (A2L, error) {
7070
a2l := A2L{}
7171
var err error
@@ -109,7 +109,7 @@ forLoop:
109109
return a2l, err
110110
}
111111

112-
//readFileToString opens and reads a file, then returns a string value
112+
// readFileToString opens and reads a file, then returns a string value
113113
func readFileToString(filepath string) (string, error) {
114114
bytesString, err := os.ReadFile(filepath)
115115
if err != nil {

a2l/a2l_test.go

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,38 @@ func FuzzParseA2L(f *testing.F) {
3232
a2lPath := "testing/ASAP2_Demo_V171_allKeywords.a2l"
3333
text, _ := readFileToString(a2lPath)
3434
f.Add(text)
35+
var errList []error
3536

3637
f.Fuzz(func(t *testing.T, orig string) {
3738
tg, err := buildTokenGeneratorFromString(orig)
3839
if err != nil {
39-
log.Err(err).Msg("could not create tokens from a2l file")
40-
log.Err(err).Msg(orig)
40+
exists := false
41+
for _, e := range errList {
42+
if err == e {
43+
exists = true
44+
break
45+
}
46+
}
47+
if !exists {
48+
errList = append(errList, err)
49+
log.Err(err).Msg("could not create tokens from a2l file")
50+
log.Err(err).Msg(orig)
51+
}
4152
}
4253
a, err := parseA2l(&tg)
4354
if err != nil {
44-
log.Err(err).Msg("failed parsing " + a.Project.Name + " with error:")
45-
log.Err(err).Msg(orig)
55+
exists := false
56+
for _, e := range errList {
57+
if err == e {
58+
exists = true
59+
break
60+
}
61+
}
62+
if !exists {
63+
errList = append(errList, err)
64+
log.Err(err).Msg("failed parsing " + a.Project.Name + " with error:")
65+
//dumps the a2l file into the log: log.Err(err).Msg(orig)
66+
}
4667
}
4768
})
4869
}
@@ -65,7 +86,7 @@ func BenchmarkParseFromFile(b *testing.B) {
6586
}
6687
}
6788

68-
//configureLogger adds a file logger, resets previous log file and does some formatting
89+
// configureLogger adds a file logger, resets previous log file and does some formatting
6990
func configureLogger() error {
7091
var err error
7192
var file *os.File

a2l/testdata/fuzz/FuzzParseA2L/290378f40701d315e4488817302849612f93373fd409f18e9bc7c479f8abcd95

Lines changed: 2 additions & 0 deletions
Large diffs are not rendered by default.

a2l/testing/ASAP2_Demo_V171_allKeywords.a2l

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ASAP2_VERSION 1 71
1+
ASAP2_VERSION 1 71
22
A2ML_VERSION 1 31
33
/begin PROJECT ASAP2_Example ""
44

@@ -2859,7 +2859,7 @@ A2ML_VERSION 1 31
28592859
SYSTEM_CONSTANT "CONTROLLERx constant1" "0.33"
28602860
SYSTEM_CONSTANT "CONTROLLERx constant2" "2.79"
28612861
/begin CALIBRATION_METHOD
2862-
„InCircuit“
2862+
„InCircuit“
28632863
2
28642864
/begin CALIBRATION_HANDLE
28652865
0x10000 /* start address of pointer table */
@@ -2870,6 +2870,8 @@ A2ML_VERSION 1 31
28702870
CALIBRATION_HANDLE_TEXT "YourTextHere"
28712871
/end CALIBRATION_HANDLE
28722872
/end CALIBRATION_METHOD
2873+
SYSTEM_CONSTANT "CONTROLLERx constant3" "0 /*blabalsdjkkasld as dsa d*/"
2874+
SYSTEM_CONSTANT "CONTROLLERx constant4" "0"
28732875
/end MOD_PAR
28742876

28752877

@@ -5729,8 +5731,8 @@ A2ML_VERSION 1 31
57295731
NO_COMPU_METHOD
57305732
10
57315733
0
5732-
25
5733-
/end TYPEDEF_AXIS
5734+
25
5735+
/end TYPEDEF_AXIS
57345736

57355737
/begin INSTANCE
57365738
Instance1

a2l/token_generator.go

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ func buildTokenGeneratorFromString(str string) (tokenGenerator, error) {
4949
str = strings.TrimFunc(str, func(r rune) bool {
5050
return !unicode.IsGraphic(r)
5151
})
52+
53+
//replace escaped quotation marks
54+
str = strings.ReplaceAll(str, `\"`, `'`)
55+
5256
//Split text file into lines and the lines into words separated by whitespace
5357
var locTokens []chan []string
5458
tokenList = make([]string, 0, expectedNumberOfTokens)
@@ -114,7 +118,8 @@ func buildTokenList(str [][]string) []string {
114118
return tl
115119
}
116120
if t != emptyToken {
117-
if strings.Contains(t, "*/") {
121+
if strings.Contains(t, "*/") && !strings.Contains(t, "*/") {
122+
log.Warn().Msg("Triggered reset! at token: " + t)
118123
//make sure that the goroutine did not start in the middle of a multiline comment.
119124
//if so then delete all previous tokens as they are part of the comment.
120125
//the buildNextValidToken routine only checks for the start of a multiline comment.
@@ -210,7 +215,7 @@ start:
210215
}
211216
}
212217

213-
//skipLineComment if a "//" is detected the token generator moves to the next line (currentOuterIndex++)
218+
// skipLineComment if a "//" is detected the token generator moves to the next line (currentOuterIndex++)
214219
func skipLineComment(currentOuterIndex *int, currentInnerIndex *int, str [][]string) (string, error) {
215220
if strings.Contains(str[*currentOuterIndex][*currentInnerIndex], beginLineCommentToken) {
216221
//move to the next line and reset inner index to 0 (first word in new line)
@@ -227,8 +232,8 @@ func skipLineComment(currentOuterIndex *int, currentInnerIndex *int, str [][]str
227232
}
228233
}
229234

230-
//skipLineComment if a "/*" is detected then token generator gets the next token until a "*/" is reached.
231-
//it will then return the next raw value token after the comment
235+
// skipLineComment if a "/*" is detected then token generator gets the next token until a "*/" is reached.
236+
// it will then return the next raw value token after the comment
232237
func skipMultilineComment(currentOuterIndex *int, currentInnerIndex *int, str [][]string) (string, error) {
233238
var err error
234239
t := str[*currentOuterIndex][*currentInnerIndex]
@@ -289,10 +294,10 @@ func getTextInQuotationMarks(currentOuterIndex *int, currentInnerIndex *int, str
289294
}
290295
}
291296

292-
//moveToNextRawValue returns back the next valid, white space separated value.
293-
//in case the line ends it restarts on the next line
294-
//in case there are no lines left and no words within the last line it will return an empty token
295-
//which is used to signal the parser that the eof has been reached.
297+
// moveToNextRawValue returns back the next valid, white space separated value.
298+
// in case the line ends it restarts on the next line
299+
// in case there are no lines left and no words within the last line it will return an empty token
300+
// which is used to signal the parser that the eof has been reached.
296301
func moveToNextRawValue(currentOuterIndex *int, currentInnerIndex *int, str [][]string) (string, error) {
297302
//If there are still tokens left in the current line
298303
if len(str[*currentOuterIndex])-1 > *currentInnerIndex && len(str[*currentOuterIndex]) > 0 {
@@ -320,17 +325,17 @@ func moveToNextRawValue(currentOuterIndex *int, currentInnerIndex *int, str [][]
320325
}
321326
}
322327

323-
//isKeyword is used in the matrixDim parser to detected when there are no dimensions left to parse
324-
//this is necessary because not every version of the a2l standard has a clear rule about how many dimensions should be expected
325-
//or are necessary to define ("1 0 0" and "1" are both valid descriptions for a curve)
328+
// isKeyword is used in the matrixDim parser to detected when there are no dimensions left to parse
329+
// this is necessary because not every version of the a2l standard has a clear rule about how many dimensions should be expected
330+
// or are necessary to define ("1 0 0" and "1" are both valid descriptions for a curve)
326331
func isKeyword(str string) bool {
327332
//look whether the given string is contained in the list of
328333
//valid a2l tokens as defined in tokens.go
329334
_, exists := keywordMap[str]
330335
return exists
331336
}
332337

333-
//getTwoWordedToken handles keywords that contain a / like e.g. "/begin CHARACTERISTIC"
338+
// getTwoWordedToken handles keywords that contain a / like e.g. "/begin CHARACTERISTIC"
334339
func getTwoWordedToken(currentOuterIndex *int, currentInnerIndex *int, str [][]string) (string, error) {
335340
var err error
336341
t := str[*currentOuterIndex][*currentInnerIndex]

a2l/tokens.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -367,9 +367,9 @@ const variablesToken = "VARIABLES"
367367
const versionToken = "VERSION"
368368
const wordToken = "WORD"
369369

370-
//keywordMap is used in the isKeyword-Funtion.
371-
//Its usage is to efficiently check whether a token is also a keyword.
372-
//Note: enum values and Standalone Keywords like "READ_ONLY" are excluded here.
370+
// keywordMap is used in the isKeyword-Funtion.
371+
// Its usage is to efficiently check whether a token is also a keyword.
372+
// Note: enum values and Standalone Keywords like "READ_ONLY" are excluded here.
373373
var keywordMap = map[string]uint8{
374374
"A2ML_VERSION": 0,
375375
"ADDR_EPK": 0,
@@ -609,7 +609,6 @@ var keywordMap = map[string]uint8{
609609
"PROJECT_NO": 0,
610610
"REF_MEMORY_SEGMENT": 0,
611611
"REF_UNIT": 0,
612-
"RESERVED": 0,
613612
"RIGHT_SHIFT": 0,
614613
"RIP_ADDR_4": 0,
615614
"RIP_ADDR_5": 0,

ihex32/hex_test.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"fmt"
66
"os"
7+
"strconv"
78
"strings"
89
"testing"
910
"time"
@@ -32,6 +33,7 @@ func FuzzParseHex(f *testing.F) {
3233
zerolog.SetGlobalLevel(zerolog.WarnLevel)
3334
hexPath := "testing/ASAP2_Demo_V171.hex"
3435
text, _ := readFileToString(hexPath)
36+
var errList []error
3537
f.Add(text)
3638

3739
f.Fuzz(func(t *testing.T, orig string) {
@@ -41,11 +43,21 @@ func FuzzParseHex(f *testing.F) {
4143
//in case unix line terminator is used.
4244
lines = strings.Split(orig, "\n")
4345
}
44-
_, err := parseHex(lines)
45-
if err != nil && err.Error() != "invalid checksums detected" {
46-
log.Err(err).Msg("could not parse hex-file")
47-
log.Err(err).Msg(orig)
48-
t.Error()
46+
h, err := parseHex(lines)
47+
if err != nil {
48+
exists := false
49+
for _, e := range errList {
50+
if err == e {
51+
exists = true
52+
break
53+
}
54+
}
55+
if !exists {
56+
errList = append(errList, err)
57+
fmt.Println(len(h))
58+
log.Err(err).Msg("could not parse hex-file with length " + strconv.Itoa(len(h)))
59+
log.Err(err).Msg(orig)
60+
}
4961
}
5062
})
5163
}

ihex32/testdata/fuzz/FuzzParseFromFile/b1c5ee6ddaa28de61bbe1205a5bf51459dbfa0d1fd12b7b4150665ffa0010e56

Lines changed: 0 additions & 2 deletions
This file was deleted.

srec19/hex_test.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"fmt"
66
"os"
7+
"strconv"
78
"strings"
89
"testing"
910
"time"
@@ -32,6 +33,7 @@ func FuzzParseHex(f *testing.F) {
3233
zerolog.SetGlobalLevel(zerolog.WarnLevel)
3334
hexPath := "testing/ASAP2_Demo_V171.s19"
3435
text, _ := readFileToString(hexPath)
36+
var errList []error
3537
f.Add(text)
3638

3739
f.Fuzz(func(t *testing.T, orig string) {
@@ -41,11 +43,21 @@ func FuzzParseHex(f *testing.F) {
4143
//in case unix line terminator is used.
4244
lines = strings.Split(orig, "\n")
4345
}
44-
_, err := parseHex(lines)
45-
if err != nil && err.Error() != "invalid checksums detected" {
46-
log.Err(err).Msg("could not parse hex-file")
47-
log.Err(err).Msg(orig)
48-
t.Error()
46+
h, err := parseHex(lines)
47+
if err != nil {
48+
exists := false
49+
for _, e := range errList {
50+
if err == e {
51+
exists = true
52+
break
53+
}
54+
}
55+
if !exists {
56+
errList = append(errList, err)
57+
fmt.Println(len(h))
58+
log.Err(err).Msg("could not parse s19-file with length " + strconv.Itoa(len(h)))
59+
log.Err(err).Msg(orig)
60+
}
4961
}
5062
})
5163
}

srec19/record.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ type record struct {
2626
func parseRecord(line string) (*record, error) {
2727
r := record{}
2828
r.recordType = line[1:2]
29-
if line[0] == beginLineToken[0] && r.recordType == "3" {
29+
if line[0] == beginLineToken[0] && r.recordType == "3" && len(line) >= 12 {
3030
r.byteCount = line[2:4]
3131
r.addressField = line[4:12]
3232
for i := 12; i < len(line)-3; i += 2 {

0 commit comments

Comments
 (0)