Skip to content

Commit

Permalink
Fix #322
Browse files Browse the repository at this point in the history
  • Loading branch information
hhrutter committed May 2, 2021
1 parent ac9adc6 commit 075feb9
Show file tree
Hide file tree
Showing 11 changed files with 50 additions and 90 deletions.
2 changes: 1 addition & 1 deletion pkg/cli/test/cli_test.go
Expand Up @@ -108,7 +108,7 @@ func TestValidate(t *testing.T) {
for _, f := range allPDFs(t, inDir) {
inFile := filepath.Join(inDir, f)
if err := validateFile(t, inFile, nil); err != nil {
t.Fatalf("%s: %v\n", msg, err)
t.Fatalf("%s: %s: %v\n", msg, inFile, err)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/pdfcpu/createAnnotations.go
Expand Up @@ -941,7 +941,7 @@ func createRemoteGoToAction(xRefTable *XRefTable) (*IndirectRef, error) {
map[string]Object{
"Type": Name("Action"),
"S": Name("GoToR"),
"F": StringLiteral(".\\/go.pdf"),
"F": StringLiteral("./go.pdf"),
"D": Array{Integer(0), Name("Fit")},
"NewWindow": Boolean(true),
},
Expand Down
29 changes: 11 additions & 18 deletions pkg/pdfcpu/crypto.go
Expand Up @@ -862,7 +862,7 @@ func validateOAndU(d Dict) (o, u []byte, err error) {
break
}
if o == nil || len(o) != 32 && len(o) != 48 {
err = errors.New("pdfcpu: unsupported encryption: required entry \"O\" missing or invalid")
err = errors.New("pdfcpu: unsupported encryption: missing or invalid required entry \"O\"")
break
}

Expand All @@ -872,7 +872,7 @@ func validateOAndU(d Dict) (o, u []byte, err error) {
break
}
if u == nil || len(u) != 32 && len(u) != 48 {
err = errors.Errorf("pdfcpu: unsupported encryption: required entry \"U\" missing or invalid %d", len(u))
err = errors.New("pdfcpu: unsupported encryption: missing or invalid required entry \"U\"")
}

break
Expand Down Expand Up @@ -1034,20 +1034,14 @@ func decryptBytes(b []byte, objNr, genNr int, encKey []byte, needAES bool, r int
}

// decryptString decrypts s using RC4 or AES.
func decryptString(s string, objNr, genNr int, key []byte, needAES bool, r int) (*string, error) {
func decryptString(s string, objNr, genNr int, key []byte, needAES bool, r int) ([]byte, error) {

b, err := Unescape(s)
bb, err := Unescape(s)
if err != nil {
return nil, err
}

b, err = decryptBytes(b, objNr, genNr, key, needAES, r)
if err != nil {
return nil, err
}

s1 := string(b)
return &s1, nil
return decryptBytes(bb, objNr, genNr, key, needAES, r)
}

func applyRC4CipherBytes(b []byte, objNr, genNr int, key []byte, needAES bool) ([]byte, error) {
Expand Down Expand Up @@ -1145,8 +1139,7 @@ func encryptDeepObject(objIn Object, objNr, genNr int, key []byte, needAES bool,
return nil, nil
}

// DecryptDeepObject recurses over non trivial PDF objects and decrypts all strings encountered.
func decryptDeepObject(objIn Object, objNr, genNr int, key []byte, needAES bool, r int) (*StringLiteral, error) {
func decryptDeepObject(objIn Object, objNr, genNr int, key []byte, needAES bool, r int) (*HexLiteral, error) {

_, ok := objIn.(IndirectRef)
if ok {
Expand Down Expand Up @@ -1178,20 +1171,20 @@ func decryptDeepObject(objIn Object, objNr, genNr int, key []byte, needAES bool,
}

case StringLiteral:
s, err := decryptString(obj.Value(), objNr, genNr, key, needAES, r)
bb, err := decryptString(obj.Value(), objNr, genNr, key, needAES, r)
if err != nil {
return nil, err
}
sl := StringLiteral(*s)
return &sl, nil
hl := NewHexLiteral(bb)
return &hl, nil

case HexLiteral:
bb, err := decryptHexLiteral(obj, objNr, genNr, key, needAES, r)
if err != nil {
return nil, err
}
sl := StringLiteral(string(bb))
return &sl, nil
hl := NewHexLiteral(bb)
return &hl, nil

default:

Expand Down
6 changes: 5 additions & 1 deletion pkg/pdfcpu/dict.go
Expand Up @@ -512,7 +512,11 @@ func (d Dict) StringEntryBytes(key string) ([]byte, error) {

s := d.StringLiteralEntry(key)
if s != nil {
return Unescape(s.Value())
bb, err := Unescape(s.Value())
if err != nil {
return nil, err
}
return bb, nil
}

h := d.HexLiteralEntry(key)
Expand Down
35 changes: 4 additions & 31 deletions pkg/pdfcpu/read.go
Expand Up @@ -1704,11 +1704,11 @@ func ParseObject(ctx *Context, offset int64, objNr, genNr int) (Object, error) {

case StringLiteral:
if ctx.EncKey != nil {
s1, err := decryptString(o.Value(), objNr, genNr, ctx.EncKey, ctx.AES4Strings, ctx.E.R)
bb, err := decryptString(o.Value(), objNr, genNr, ctx.EncKey, ctx.AES4Strings, ctx.E.R)
if err != nil {
return nil, err
}
return StringLiteral(*s1), nil
return NewHexLiteral(bb), nil
}
return o, nil

Expand All @@ -1718,7 +1718,7 @@ func ParseObject(ctx *Context, offset int64, objNr, genNr int) (Object, error) {
if err != nil {
return nil, err
}
return StringLiteral(string(bb)), nil
return NewHexLiteral(bb), nil
}
return o, nil

Expand Down Expand Up @@ -2477,32 +2477,6 @@ func handleUnencryptedFile(ctx *Context) error {
return nil
}

func idBytes(ctx *Context) (id []byte, err error) {

if ctx.ID == nil {
return nil, errors.New("pdfcpu: missing ID entry")
}

hl, ok := ctx.ID[0].(HexLiteral)
if ok {
id, err = hl.Bytes()
if err != nil {
return nil, err
}
} else {
sl, ok := ctx.ID[0].(StringLiteral)
if !ok {
return nil, errors.New("pdfcpu: ID must contain hex literals or string literals")
}
id, err = Unescape(sl.Value())
if err != nil {
return nil, err
}
}

return id, nil
}

func needsOwnerAndUserPassword(cmd CommandMode) bool {

return cmd == CHANGEOPW || cmd == CHANGEUPW || cmd == SETPERMISSIONS
Expand Down Expand Up @@ -2535,8 +2509,7 @@ func setupEncryptionKey(ctx *Context, d Dict) (err error) {
return err
}

ctx.E.ID, err = idBytes(ctx)
if err != nil {
if ctx.E.ID, err = ctx.IDFirstElement(); err != nil {
return err
}

Expand Down
12 changes: 6 additions & 6 deletions pkg/pdfcpu/utf16.go
Expand Up @@ -50,7 +50,7 @@ func IsUTF16BE(b []byte) bool {
func decodeUTF16String(b []byte) (string, error) {
// We only accept big endian byte order.
if !IsUTF16BE(b) {
log.Debug.Printf("decodeUTF16String: not UTF16BE: %v\n", b)
log.Debug.Printf("decodeUTF16String: not UTF16BE: %s\n", hex.Dump(b))
return "", ErrInvalidUTF16BE
}

Expand Down Expand Up @@ -119,13 +119,13 @@ func encodeUTF16String(s string) string {
}

// StringLiteralToString returns the best possible string rep for a string literal.
func StringLiteralToString(s string) (string, error) {
b, err := Unescape(s)
func StringLiteralToString(sl StringLiteral) (string, error) {
bb, err := Unescape(sl.Value())
if err != nil {
return "", err
}

s1 := string(b)
s1 := string(bb)

// Check for Big Endian UTF-16.
if IsStringUTF16BE(s1) {
Expand All @@ -140,9 +140,9 @@ func StringLiteralToString(s string) (string, error) {
}

// HexLiteralToString returns a possibly UTF16 encoded string for a hex string.
func HexLiteralToString(hexString string) (string, error) {
func HexLiteralToString(hl HexLiteral) (string, error) {
// Get corresponding byte slice.
b, err := hex.DecodeString(hexString)
b, err := hex.DecodeString(hl.Value())
if err != nil {
return "", err
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/pdfcpu/validate/action.go
Expand Up @@ -477,7 +477,7 @@ func validateHideActionDictEntryT(xRefTable *pdf.XRefTable, o pdf.Object) error

case pdf.StringLiteral:
// Ensure UTF16 correctness.
_, err := pdf.StringLiteralToString(o.Value())
_, err := pdf.StringLiteralToString(o)
if err != nil {
return err
}
Expand Down Expand Up @@ -506,7 +506,7 @@ func validateHideActionDictEntryT(xRefTable *pdf.XRefTable, o pdf.Object) error

case pdf.StringLiteral:
// Ensure UTF16 correctness.
_, err = pdf.StringLiteralToString(o.Value())
_, err = pdf.StringLiteralToString(o)
if err != nil {
return err
}
Expand Down Expand Up @@ -664,11 +664,11 @@ func validateJavaScript(xRefTable *pdf.XRefTable, d pdf.Dict, dictName, entryNam

case pdf.StringLiteral:
// Ensure UTF16 correctness.
_, err = pdf.StringLiteralToString(o.Value())
_, err = pdf.StringLiteralToString(o)

case pdf.HexLiteral:
// Ensure UTF16 correctness.
_, err = pdf.HexLiteralToString(o.Value())
_, err = pdf.HexLiteralToString(o)

case pdf.StreamDict:
// no further processing
Expand Down
8 changes: 4 additions & 4 deletions pkg/pdfcpu/validate/objects.go
Expand Up @@ -1015,10 +1015,10 @@ func validateString(xRefTable *pdf.XRefTable, o pdf.Object, validate func(string
switch o := o.(type) {

case pdf.StringLiteral:
s, err = pdf.StringLiteralToString(o.Value())
s, err = pdf.StringLiteralToString(o)

case pdf.HexLiteral:
s, err = pdf.HexLiteralToString(o.Value())
s, err = pdf.HexLiteralToString(o)

default:
err = errors.New("pdfcpu: validateString: invalid type")
Expand Down Expand Up @@ -1070,10 +1070,10 @@ func validateStringEntry(xRefTable *pdf.XRefTable, d pdf.Dict, dictName, entryNa
switch o := o.(type) {

case pdf.StringLiteral:
s, err = pdf.StringLiteralToString(o.Value())
s, err = pdf.StringLiteralToString(o)

case pdf.HexLiteral:
s, err = pdf.HexLiteralToString(o.Value())
s, err = pdf.HexLiteralToString(o)

default:
err = errors.Errorf("pdfcpu: validateStringEntry: dict=%s entry=%s invalid type", dictName, entryName)
Expand Down
5 changes: 1 addition & 4 deletions pkg/pdfcpu/write.go
Expand Up @@ -833,13 +833,10 @@ func setupEncryption(ctx *Context) error {
return errors.New("pdfcpu: encrypt: missing ID")
}

var id []byte
if id, err = ctx.IDFirstElement(); err != nil {
if ctx.E.ID, err = ctx.IDFirstElement(); err != nil {
return err
}

ctx.E.ID = id

if err = calcOAndU(ctx, d); err != nil {
return err
}
Expand Down
18 changes: 5 additions & 13 deletions pkg/pdfcpu/writeImage.go
Expand Up @@ -116,30 +116,22 @@ func pdfImage(xRefTable *XRefTable, sd *StreamDict, objNr int) (*PDFImage, error
// Identify the color lookup table for an Indexed color space.
func colorLookupTable(xRefTable *XRefTable, o Object) ([]byte, error) {

var lookup []byte
var err error

o, _ = xRefTable.Dereference(o)

switch o := o.(type) {

case StringLiteral:
return Unescape(string(o))
return []byte(o), nil

case HexLiteral:
lookup, err = o.Bytes()
if err != nil {
return nil, err
}
return o.Bytes()

case StreamDict:
lookup, err = streamBytes(&o)
if err != nil || lookup == nil {
return nil, err
}
return streamBytes(&o)

}

return lookup, nil
return nil, nil
}

func decodePixelColorValue(p uint8, bpc, c int, decode []colValRange) uint8 {
Expand Down
15 changes: 8 additions & 7 deletions pkg/pdfcpu/xreftable.go
Expand Up @@ -932,7 +932,7 @@ func (xRefTable *XRefTable) DereferenceStringLiteral(o Object, sinceVersion Vers
}

// Ensure UTF16 correctness.
s1, err := StringLiteralToString(s.Value())
s1, err := StringLiteralToString(s)
if err != nil {
return s, err
}
Expand Down Expand Up @@ -962,18 +962,18 @@ func (xRefTable *XRefTable) DereferenceStringOrHexLiteral(obj Object, sinceVersi

case StringLiteral:
// Ensure UTF16 correctness.
if s, err = StringLiteralToString(str.Value()); err != nil {
if s, err = StringLiteralToString(str); err != nil {
return "", err
}

case HexLiteral:
// Ensure UTF16 correctness.
if s, err = HexLiteralToString(str.Value()); err != nil {
if s, err = HexLiteralToString(str); err != nil {
return "", err
}

default:
return "", errors.Errorf("pdfcpu: dereferenceStringOrHexLiteral: wrong type <%v>", obj)
return "", errors.Errorf("pdfcpu: dereferenceStringOrHexLiteral: wrong type %T", obj)

}

Expand All @@ -994,9 +994,9 @@ func (xRefTable *XRefTable) DereferenceStringOrHexLiteral(obj Object, sinceVersi
func Text(o Object) (string, error) {
switch obj := o.(type) {
case StringLiteral:
return StringLiteralToString(obj.Value())
return StringLiteralToString(obj)
case HexLiteral:
return HexLiteralToString(obj.Value())
return HexLiteralToString(obj)
default:
return "", errors.Errorf("pdfcpu: text: corrupt - %v\n", obj)
}
Expand Down Expand Up @@ -1640,7 +1640,8 @@ func (xRefTable *XRefTable) IDFirstElement() (id []byte, err error) {
return nil, errors.New("pdfcpu: ID must contain hex literals or string literals")
}

return Unescape(sl.Value())
//return Unescape(sl.Value())
return []byte(sl), nil
}

// InheritedPageAttrs represents all inherited page attributes.
Expand Down

0 comments on commit 075feb9

Please sign in to comment.