return err
}
-// Encode writes the Block b to out.
+// Encode writes the PEM encoding of b to out.
func Encode(out io.Writer, b *Block) error {
+ // Check for invalid block before writing any output.
+ for k := range b.Headers {
+ if strings.Contains(k, ":") {
+ return errors.New("pem: cannot encode a header key that contains a colon")
+ }
+ }
+
+ // All errors below are relayed from underlying io.Writer,
+ // so it is now safe to write data.
+
if _, err := out.Write(pemStart[1:]); err != nil {
return err
}
// For consistency of output, write other headers sorted by key.
sort.Strings(h)
for _, k := range h {
- if strings.Contains(k, ":") {
- return errors.New("pem: cannot encode a header key that contains a colon")
- }
if err := writeHeader(out, k, b.Headers[k]); err != nil {
return err
}
return err
}
-// EncodeToMemory returns the Block b.
+// EncodeToMemory returns the PEM encoding of b.
//
-// EncodeToMemory will return an incomplete PEM encoded structure if an invalid block is given.
-// To catch errors, Blocks with user-supplied headers should use Encode.
+// If b has invalid headers and cannot be encoded,
+// EncodeToMemory returns nil. If it is important to
+// report details about this error case, use Encode instead.
func EncodeToMemory(b *Block) []byte {
var buf bytes.Buffer
- Encode(&buf, b)
+ if err := Encode(&buf, b); err != nil {
+ return nil
+ }
return buf.Bytes()
}
tJQLJRZ+ItT5Irl4owSEBNLahC1j3fhQavbj9WVAfKk=
-----END RSA PRIVATE KEY-----
`
+
+func TestBadEncode(t *testing.T) {
+ b := &Block{Type: "BAD", Headers: map[string]string{"X:Y": "Z"}}
+ var buf bytes.Buffer
+ if err := Encode(&buf, b); err == nil {
+ t.Fatalf("Encode did not report invalid header")
+ }
+ if buf.Len() != 0 {
+ t.Fatalf("Encode wrote data before reporting invalid header")
+ }
+ if data := EncodeToMemory(b); data != nil {
+ t.Fatalf("EncodeToMemory returned non-nil data")
+ }
+}