From b6496c2d20904e665116133a9e9bf9ae6e3b45b8 Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Wed, 2 Feb 2022 04:08:55 -0500 Subject: add internal/cpe --- internal/cpe/cpe.go | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 internal/cpe/cpe.go (limited to 'internal/cpe/cpe.go') diff --git a/internal/cpe/cpe.go b/internal/cpe/cpe.go new file mode 100644 index 0000000..73930e8 --- /dev/null +++ b/internal/cpe/cpe.go @@ -0,0 +1,94 @@ +// CPE 2.3 formatted string parser. +// +// Source: NISTIR 7605, figure 6-3: +// https://nvlpubs.nist.gov/nistpubs/Legacy/IR/nistir7695.pdf +package cpe + +import ( + "fmt" +) + +//go:generate stringer -linecomment -type=tokenType + +// token type +type tokenType byte + +const ( + anyToken tokenType = iota // any + naToken // na + valToken // val +) + +// token +type token struct { + Type tokenType // token type + Val string // token value +} + +// parse buffer into token. +func newToken(val []byte) token { + if len(val) > 0 { + switch val[0] { + case '*': + return token { Type: anyToken } + case '-': + return token { Type: naToken } + default: + return token { Type: valToken, Val: string(val) } + } + } else { + // empty value + return token { Type: valToken, Val: "" } + } +} + +// Parse buffer into slice of tokens. +func tokenize(buf []byte) ([]token, error) { + // build result + var r []token + + // current token and escape state + var curr []byte + esc := false + + // build result + for _, b := range(buf) { + if esc { + switch b { + // valid escaped characters + case '\\', '*', '-', '!', '"', '#', '$', '%', '&', '\'', '(', ')', + '+', ',', '/', ':', ';', '<', '=', '>', '@', '[', ']', '^', '`', + '{', '|', '}', '~': + curr = append(curr, b) + esc = false + default: + return r, fmt.Errorf("invalid escape byte: 0x%02x", b) + } + } else { + switch b { + case '\\': + esc = true + case ':': + // push token, clear buffer + r = append(r, newToken(curr)) + curr = nil + case 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '-', '.', '_', '*', '?': + curr = append(curr, b) + default: + return r, fmt.Errorf("invalid byte: 0x%02x", b) + } + } + } + + if len(curr) > 0 { + // push token, clear buffer + r = append(r, newToken(curr)) + curr = nil + } + + // return success + return r, nil +} -- cgit v1.2.3