Pārlūkot izejas kodu

daemon/config: inform the user when the input JSON contains invalid UTF-8

This helps ensure that users are not surprised by unexpected tokens in
the JSON parser, or fallout later in the daemon.

Signed-off-by: Bjorn Neergaard <bneergaard@mirantis.com>
Bjorn Neergaard 2 gadi atpakaļ
vecāks
revīzija
8dbc5df952
2 mainītis faili ar 15 papildinājumiem un 3 dzēšanām
  1. 3 3
      daemon/config/config.go
  2. 12 0
      daemon/config/config_test.go

+ 3 - 3
daemon/config/config.go

@@ -11,6 +11,7 @@ import (
 	"strings"
 	"sync"
 
+	"golang.org/x/text/encoding"
 	"golang.org/x/text/encoding/unicode"
 	"golang.org/x/text/transform"
 
@@ -438,10 +439,9 @@ func getConflictFreeConfiguration(configFile string, flags *pflag.FlagSet) (*Con
 	// [RFC 8259 Section 8.1]: https://www.rfc-editor.org/rfc/rfc8259#section-8.1
 	// [RFC 7159 Section 8.1]: https://www.rfc-editor.org/rfc/rfc7159#section-8.1
 	// [Windows PowerShell]: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_character_encoding?view=powershell-5.1
-	decoder := unicode.BOMOverride(unicode.UTF8.NewDecoder())
-	b, _, err = transform.Bytes(decoder, b)
+	b, n, err := transform.Bytes(transform.Chain(unicode.BOMOverride(transform.Nop), encoding.UTF8Validator), b)
 	if err != nil {
-		return nil, err
+		return nil, errors.Wrapf(err, "failed to decode configuration JSON at offset %d", n)
 	}
 	// Trim whitespace so that an empty config can be detected for an early return.
 	b = bytes.TrimSpace(b)

+ 12 - 0
daemon/config/config_test.go

@@ -77,6 +77,18 @@ func TestDaemonConfigurationUnicodeVariations(t *testing.T) {
 	}
 }
 
+// TestDaemonConfigurationInvalidUnicode ensures that the JSON parser returns a useful error message if malformed UTF-8
+// is provided.
+func TestDaemonConfigurationInvalidUnicode(t *testing.T) {
+	configFileBOM := makeConfigFile(t, "\xef\xbb\xbf{\"debug\": true}\xff")
+	_, err := MergeDaemonConfigurations(&Config{}, nil, configFileBOM)
+	assert.ErrorIs(t, err, encoding.ErrInvalidUTF8)
+
+	configFileNoBOM := makeConfigFile(t, "{\"debug\": true}\xff")
+	_, err = MergeDaemonConfigurations(&Config{}, nil, configFileNoBOM)
+	assert.ErrorIs(t, err, encoding.ErrInvalidUTF8)
+}
+
 func TestFindConfigurationConflicts(t *testing.T) {
 	config := map[string]interface{}{"authorization-plugins": "foobar"}
 	flags := pflag.NewFlagSet("test", pflag.ContinueOnError)