mirror of
https://github.com/miekg/dns.git
synced 2025-12-16 09:11:34 +01:00
Avoid using strings.Split (#1501)
* Avoid using strings.Split strings.Split has to allocate for the return slice. This allocation was wasteful in ever case it was used in this library. Instead we use the new strings.Cut and other string manipulation where appropriate. This tends to lead to cleaner and more readable code in addition to the benefits this has on the garbage collector. * Further simplify structTag in the msg_generate.go This doesn't need to call strings.TrimPrefix twice.
This commit is contained in:
parent
b18c05cc13
commit
02e9e72099
@ -37,7 +37,8 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
|
|||||||
return nil, ErrPrivKey
|
return nil, ErrPrivKey
|
||||||
}
|
}
|
||||||
// TODO(mg): check if the pubkey matches the private key
|
// TODO(mg): check if the pubkey matches the private key
|
||||||
algo, err := strconv.ParseUint(strings.SplitN(m["algorithm"], " ", 2)[0], 10, 8)
|
algoStr, _, _ := strings.Cut(m["algorithm"], " ")
|
||||||
|
algo, err := strconv.ParseUint(algoStr, 10, 8)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ErrPrivKey
|
return nil, ErrPrivKey
|
||||||
}
|
}
|
||||||
|
|||||||
33
generate.go
33
generate.go
@ -35,17 +35,17 @@ func (zp *ZoneParser) generate(l lex) (RR, bool) {
|
|||||||
token = token[:i]
|
token = token[:i]
|
||||||
}
|
}
|
||||||
|
|
||||||
sx := strings.SplitN(token, "-", 2)
|
startStr, endStr, ok := strings.Cut(token, "-")
|
||||||
if len(sx) != 2 {
|
if !ok {
|
||||||
return zp.setParseError("bad start-stop in $GENERATE range", l)
|
return zp.setParseError("bad start-stop in $GENERATE range", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
start, err := strconv.ParseInt(sx[0], 10, 64)
|
start, err := strconv.ParseInt(startStr, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return zp.setParseError("bad start in $GENERATE range", l)
|
return zp.setParseError("bad start in $GENERATE range", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
end, err := strconv.ParseInt(sx[1], 10, 64)
|
end, err := strconv.ParseInt(endStr, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return zp.setParseError("bad stop in $GENERATE range", l)
|
return zp.setParseError("bad stop in $GENERATE range", l)
|
||||||
}
|
}
|
||||||
@ -54,7 +54,7 @@ func (zp *ZoneParser) generate(l lex) (RR, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// _BLANK
|
// _BLANK
|
||||||
l, ok := zp.c.Next()
|
l, ok = zp.c.Next()
|
||||||
if !ok || l.value != zBlank {
|
if !ok || l.value != zBlank {
|
||||||
return zp.setParseError("garbage after $GENERATE range", l)
|
return zp.setParseError("garbage after $GENERATE range", l)
|
||||||
}
|
}
|
||||||
@ -211,15 +211,16 @@ func (r *generateReader) ReadByte() (byte, error) {
|
|||||||
func modToPrintf(s string) (string, int64, string) {
|
func modToPrintf(s string) (string, int64, string) {
|
||||||
// Modifier is { offset [ ,width [ ,base ] ] } - provide default
|
// Modifier is { offset [ ,width [ ,base ] ] } - provide default
|
||||||
// values for optional width and type, if necessary.
|
// values for optional width and type, if necessary.
|
||||||
var offStr, widthStr, base string
|
offStr, s, ok0 := strings.Cut(s, ",")
|
||||||
switch xs := strings.Split(s, ","); len(xs) {
|
widthStr, s, ok1 := strings.Cut(s, ",")
|
||||||
case 1:
|
base, _, ok2 := strings.Cut(s, ",")
|
||||||
offStr, widthStr, base = xs[0], "0", "d"
|
if !ok0 {
|
||||||
case 2:
|
widthStr = "0"
|
||||||
offStr, widthStr, base = xs[0], xs[1], "d"
|
}
|
||||||
case 3:
|
if !ok1 {
|
||||||
offStr, widthStr, base = xs[0], xs[1], xs[2]
|
base = "d"
|
||||||
default:
|
}
|
||||||
|
if ok2 {
|
||||||
return "", 0, "bad modifier in $GENERATE"
|
return "", 0, "bad modifier in $GENERATE"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,8 +235,8 @@ func modToPrintf(s string) (string, int64, string) {
|
|||||||
return "", 0, "bad offset in $GENERATE"
|
return "", 0, "bad offset in $GENERATE"
|
||||||
}
|
}
|
||||||
|
|
||||||
width, err := strconv.ParseInt(widthStr, 10, 64)
|
width, err := strconv.ParseUint(widthStr, 10, 8)
|
||||||
if err != nil || width < 0 || width > 255 {
|
if err != nil {
|
||||||
return "", 0, "bad width in $GENERATE"
|
return "", 0, "bad width in $GENERATE"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -327,25 +327,15 @@ return off, nil
|
|||||||
|
|
||||||
// structMember will take a tag like dns:"size-base32:SaltLength" and return the last part of this string.
|
// structMember will take a tag like dns:"size-base32:SaltLength" and return the last part of this string.
|
||||||
func structMember(s string) string {
|
func structMember(s string) string {
|
||||||
fields := strings.Split(s, ":")
|
idx := strings.LastIndex(s, ":")
|
||||||
if len(fields) == 0 {
|
return strings.TrimSuffix(s[idx+1:], `"`)
|
||||||
return ""
|
|
||||||
}
|
|
||||||
f := fields[len(fields)-1]
|
|
||||||
// f should have a closing "
|
|
||||||
if len(f) > 1 {
|
|
||||||
return f[:len(f)-1]
|
|
||||||
}
|
|
||||||
return f
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// structTag will take a tag like dns:"size-base32:SaltLength" and return base32.
|
// structTag will take a tag like dns:"size-base32:SaltLength" and return base32.
|
||||||
func structTag(s string) string {
|
func structTag(s string) string {
|
||||||
fields := strings.Split(s, ":")
|
s = strings.TrimPrefix(s, `dns:"size-`)
|
||||||
if len(fields) < 2 {
|
s, _, _ = strings.Cut(s, ":")
|
||||||
return ""
|
return s
|
||||||
}
|
|
||||||
return fields[1][len("\"size-"):]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func fatalIfErr(err error) {
|
func fatalIfErr(err error) {
|
||||||
|
|||||||
49
scan.go
49
scan.go
@ -1216,42 +1216,34 @@ func stringToCm(token string) (e, m uint8, ok bool) {
|
|||||||
if token[len(token)-1] == 'M' || token[len(token)-1] == 'm' {
|
if token[len(token)-1] == 'M' || token[len(token)-1] == 'm' {
|
||||||
token = token[0 : len(token)-1]
|
token = token[0 : len(token)-1]
|
||||||
}
|
}
|
||||||
s := strings.SplitN(token, ".", 2)
|
|
||||||
var meters, cmeters, val int
|
var (
|
||||||
var err error
|
meters, cmeters, val int
|
||||||
switch len(s) {
|
err error
|
||||||
case 2:
|
)
|
||||||
if cmeters, err = strconv.Atoi(s[1]); err != nil {
|
mStr, cmStr, hasCM := strings.Cut(token, ".")
|
||||||
return
|
if hasCM {
|
||||||
}
|
|
||||||
// There's no point in having more than 2 digits in this part, and would rather make the implementation complicated ('123' should be treated as '12').
|
// There's no point in having more than 2 digits in this part, and would rather make the implementation complicated ('123' should be treated as '12').
|
||||||
// So we simply reject it.
|
// So we simply reject it.
|
||||||
// We also make sure the first character is a digit to reject '+-' signs.
|
// We also make sure the first character is a digit to reject '+-' signs.
|
||||||
if len(s[1]) > 2 || s[1][0] < '0' || s[1][0] > '9' {
|
cmeters, err = strconv.Atoi(cmStr)
|
||||||
|
if err != nil || len(cmStr) > 2 || cmStr[0] < '0' || cmStr[0] > '9' {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(s[1]) == 1 {
|
if len(cmStr) == 1 {
|
||||||
// 'nn.1' must be treated as 'nn-meters and 10cm, not 1cm.
|
// 'nn.1' must be treated as 'nn-meters and 10cm, not 1cm.
|
||||||
cmeters *= 10
|
cmeters *= 10
|
||||||
}
|
}
|
||||||
if s[0] == "" {
|
|
||||||
// This will allow omitting the 'meter' part, like .01 (meaning 0.01m = 1cm).
|
|
||||||
break
|
|
||||||
}
|
|
||||||
fallthrough
|
|
||||||
case 1:
|
|
||||||
if meters, err = strconv.Atoi(s[0]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// RFC1876 states the max value is 90000000.00. The latter two conditions enforce it.
|
|
||||||
if s[0][0] < '0' || s[0][0] > '9' || meters > 90000000 || (meters == 90000000 && cmeters != 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case 0:
|
|
||||||
// huh?
|
|
||||||
return 0, 0, false
|
|
||||||
}
|
}
|
||||||
ok = true
|
// This slighly ugly condition will allow omitting the 'meter' part, like .01 (meaning 0.01m = 1cm).
|
||||||
|
if !hasCM || mStr != "" {
|
||||||
|
meters, err = strconv.Atoi(mStr)
|
||||||
|
// RFC1876 states the max value is 90000000.00. The latter two conditions enforce it.
|
||||||
|
if err != nil || mStr[0] < '0' || mStr[0] > '9' || meters > 90000000 || (meters == 90000000 && cmeters != 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if meters > 0 {
|
if meters > 0 {
|
||||||
e = 2
|
e = 2
|
||||||
val = meters
|
val = meters
|
||||||
@ -1263,8 +1255,7 @@ func stringToCm(token string) (e, m uint8, ok bool) {
|
|||||||
e++
|
e++
|
||||||
val /= 10
|
val /= 10
|
||||||
}
|
}
|
||||||
m = uint8(val)
|
return e, uint8(val), true
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func toAbsoluteName(name, origin string) (absolute string, ok bool) {
|
func toAbsoluteName(name, origin string) (absolute string, ok bool) {
|
||||||
|
|||||||
39
svcb.go
39
svcb.go
@ -314,10 +314,11 @@ func (s *SVCBMandatory) unpack(b []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *SVCBMandatory) parse(b string) error {
|
func (s *SVCBMandatory) parse(b string) error {
|
||||||
str := strings.Split(b, ",")
|
codes := make([]SVCBKey, 0, strings.Count(b, ",")+1)
|
||||||
codes := make([]SVCBKey, 0, len(str))
|
for len(b) > 0 {
|
||||||
for _, e := range str {
|
var key string
|
||||||
codes = append(codes, svcbStringToKey(e))
|
key, b, _ = strings.Cut(b, ",")
|
||||||
|
codes = append(codes, svcbStringToKey(key))
|
||||||
}
|
}
|
||||||
s.Code = codes
|
s.Code = codes
|
||||||
return nil
|
return nil
|
||||||
@ -613,19 +614,24 @@ func (s *SVCBIPv4Hint) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *SVCBIPv4Hint) parse(b string) error {
|
func (s *SVCBIPv4Hint) parse(b string) error {
|
||||||
|
if b == "" {
|
||||||
|
return errors.New("dns: svcbipv4hint: empty hint")
|
||||||
|
}
|
||||||
if strings.Contains(b, ":") {
|
if strings.Contains(b, ":") {
|
||||||
return errors.New("dns: svcbipv4hint: expected ipv4, got ipv6")
|
return errors.New("dns: svcbipv4hint: expected ipv4, got ipv6")
|
||||||
}
|
}
|
||||||
str := strings.Split(b, ",")
|
|
||||||
dst := make([]net.IP, len(str))
|
hint := make([]net.IP, 0, strings.Count(b, ",")+1)
|
||||||
for i, e := range str {
|
for len(b) > 0 {
|
||||||
|
var e string
|
||||||
|
e, b, _ = strings.Cut(b, ",")
|
||||||
ip := net.ParseIP(e).To4()
|
ip := net.ParseIP(e).To4()
|
||||||
if ip == nil {
|
if ip == nil {
|
||||||
return errors.New("dns: svcbipv4hint: bad ip")
|
return errors.New("dns: svcbipv4hint: bad ip")
|
||||||
}
|
}
|
||||||
dst[i] = ip
|
hint = append(hint, ip)
|
||||||
}
|
}
|
||||||
s.Hint = dst
|
s.Hint = hint
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -733,9 +739,14 @@ func (s *SVCBIPv6Hint) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *SVCBIPv6Hint) parse(b string) error {
|
func (s *SVCBIPv6Hint) parse(b string) error {
|
||||||
str := strings.Split(b, ",")
|
if b == "" {
|
||||||
dst := make([]net.IP, len(str))
|
return errors.New("dns: svcbipv6hint: empty hint")
|
||||||
for i, e := range str {
|
}
|
||||||
|
|
||||||
|
hint := make([]net.IP, 0, strings.Count(b, ",")+1)
|
||||||
|
for len(b) > 0 {
|
||||||
|
var e string
|
||||||
|
e, b, _ = strings.Cut(b, ",")
|
||||||
ip := net.ParseIP(e)
|
ip := net.ParseIP(e)
|
||||||
if ip == nil {
|
if ip == nil {
|
||||||
return errors.New("dns: svcbipv6hint: bad ip")
|
return errors.New("dns: svcbipv6hint: bad ip")
|
||||||
@ -743,9 +754,9 @@ func (s *SVCBIPv6Hint) parse(b string) error {
|
|||||||
if ip.To4() != nil {
|
if ip.To4() != nil {
|
||||||
return errors.New("dns: svcbipv6hint: expected ipv6, got ipv4-mapped-ipv6")
|
return errors.New("dns: svcbipv6hint: expected ipv6, got ipv4-mapped-ipv6")
|
||||||
}
|
}
|
||||||
dst[i] = ip
|
hint = append(hint, ip)
|
||||||
}
|
}
|
||||||
s.Hint = dst
|
s.Hint = hint
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -283,9 +283,8 @@ func main() {
|
|||||||
if sl, ok := st.Field(i).Type().(*types.Slice); ok {
|
if sl, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||||
t := sl.Underlying().String()
|
t := sl.Underlying().String()
|
||||||
t = strings.TrimPrefix(t, "[]")
|
t = strings.TrimPrefix(t, "[]")
|
||||||
if strings.Contains(t, ".") {
|
if idx := strings.LastIndex(t, "."); idx >= 0 {
|
||||||
splits := strings.Split(t, ".")
|
t = t[idx+1:]
|
||||||
t = splits[len(splits)-1]
|
|
||||||
}
|
}
|
||||||
// For the EDNS0 interface (and others), we need to call the copy method on each element.
|
// For the EDNS0 interface (and others), we need to call the copy method on each element.
|
||||||
if t == "EDNS0" || t == "APLPrefix" || t == "SVCBKeyValue" {
|
if t == "EDNS0" || t == "APLPrefix" || t == "SVCBKeyValue" {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user