diff --git a/decrypt_test.go b/decrypt_test.go
index d71a0d3..d1533ee 100644
--- a/decrypt_test.go
+++ b/decrypt_test.go
@@ -139,7 +139,7 @@ func (testSuite *DecryptTest) TestInvalid(c *C) {
c.Assert(err, IsNil)
_, err = Decrypt(testSuite.Key, []byte(""))
c.Assert(err, ErrorMatches, "xmlSecFindNode cannot find EncryptedData node")
@@ -149,7 +149,7 @@ func (testSuite *DecryptTest) TestInvalid(c *C) {
docStr = []byte(`https://idp.testshib.org/idp/shibbolethinvalid<`)
_, err = Decrypt(testSuite.Key, docStr)
- c.Assert(err, ErrorMatches, "malformed XML")
+ c.Assert(err, ErrorMatches, ".*Premature end of data in tag.*")
docStr = []byte(`
diff --git a/encrypt_realworld_test.go b/encrypt_realworld_test.go
index 543873c..33bbbbe 100644
--- a/encrypt_realworld_test.go
+++ b/encrypt_realworld_test.go
@@ -95,7 +95,7 @@ func (testSuite *XmlencRealWorldTest) TestInvalid(c *C) {
c.Assert(err, IsNil)
_, err = Decrypt(testSuite.Key, []byte(""))
c.Assert(err, ErrorMatches, "xmlSecFindNode cannot find EncryptedData node")
@@ -105,7 +105,7 @@ func (testSuite *XmlencRealWorldTest) TestInvalid(c *C) {
docStr := []byte(`https://idp.testshib.org/idp/shibbolethinvalid<`)
_, err = Decrypt(testSuite.Key, docStr)
- c.Assert(err, ErrorMatches, "malformed XML")
+ c.Assert(err, ErrorMatches, ".*Premature end of data in tag.*")
docStr = []byte(`
diff --git a/error.go b/error.go
index dfce98f..414b593 100644
--- a/error.go
+++ b/error.go
@@ -4,6 +4,7 @@ import (
"C"
"fmt"
"runtime"
+ "strings"
"github.com/crewjam/errset"
)
@@ -32,8 +33,8 @@ func (e libraryError) Error() string {
e.Message)
}
-//export onError
-func onError(file *C.char, line C.int, funcName *C.char, errorObject *C.char, errorSubject *C.char, reason C.int, msg *C.char) {
+//export onXmlsecError
+func onXmlsecError(file *C.char, line C.int, funcName *C.char, errorObject *C.char, errorSubject *C.char, reason C.int, msg *C.char) {
err := libraryError{
FuncName: C.GoString(funcName),
FileName: C.GoString(file),
@@ -46,6 +47,13 @@ func onError(file *C.char, line C.int, funcName *C.char, errorObject *C.char, er
globalErrors[threadID] = append(globalErrors[threadID], err)
}
+//export onXmlError
+func onXmlError(msg *C.char) {
+ threadID := getThreadID()
+ globalErrors[threadID] = append(globalErrors[threadID],
+ fmt.Errorf("%s", strings.TrimSuffix(C.GoString(msg), "\n")))
+}
+
// startProcessingXML is called whenever we enter a function exported by this package.
// It locks the current goroutine to the current thread and establishes a thread-local
// error object. If the library later calls onError then the error will be appended
diff --git a/error_thunk.go b/error_thunk.go
index d6211a4..068f12d 100644
--- a/error_thunk.go
+++ b/error_thunk.go
@@ -1,13 +1,31 @@
package xmlsec
-// onError_cgo is a C function that can be passed to xmlSecErrorsSetCallback which
-// in turn invokes the go function onError which captures errors generated by
-// libxmlsec.
+// #include
+// #include
+// #include
+// #include
+// #include
+// #include
+// #include
//
-// For reasons I do not completely understand, it must be defined in a different
-// file from onError.
-
-// void onError_cgo(char *file, int line, char *funcName, char *errorObject, char *errorSubject, int reason, char *msg) {
-// onError(file, line, funcName, errorObject, errorSubject, reason, msg);
+// void onXmlError(const char *msg); // implemented in go
+// void onXmlsecError(const char *file, int line, const char *funcName, const char *errorObject, const char *errorSubject, int reason, const char *msg); // implemented in go
+//
+// static void onXmlGenericError_cgo(void *ctx, const char *format, ...) {
+// char buffer[256];
+// va_list args;
+// va_start(args, format);
+// vsnprintf(buffer, 256, format, args);
+// va_end (args);
+// onXmlError(buffer);
+// }
+//
+// static void onXmlsecError_cgo(const char *file, int line, const char *funcName, const char *errorObject, const char *errorSubject, int reason, const char *msg) {
+// onXmlsecError(file, line, funcName, errorObject, errorSubject, reason, msg);
+// }
+//
+// void captureXmlErrors() {
+// xmlSecErrorsSetCallback(onXmlsecError_cgo);
+// xmlSetGenericErrorFunc(NULL, onXmlGenericError_cgo);
// }
import "C"
diff --git a/xmldsig_test.go b/xmldsig_test.go
index b699179..42b52f5 100644
--- a/xmldsig_test.go
+++ b/xmldsig_test.go
@@ -218,7 +218,7 @@ func (testSuite *XMLDSigTest) TestVerifyFailsWhenMessageModified(c *C) {
func (testSuite *XMLDSigTest) TestInvalidXML(c *C) {
_, err := Sign(testSuite.Key, []byte(""), SignatureOptions{})
c.Assert(err, ErrorMatches, "cannot find start node")
@@ -227,7 +227,7 @@ func (testSuite *XMLDSigTest) TestInvalidXML(c *C) {
c.Assert(err, ErrorMatches, "failed to load pem key")
err = Verify(testSuite.Cert, []byte(""), SignatureOptions{})
c.Assert(err, ErrorMatches, "cannot find start node")
diff --git a/xmlsec.go b/xmlsec.go
index f66a528..8b1029d 100644
--- a/xmlsec.go
+++ b/xmlsec.go
@@ -1,9 +1,6 @@
package xmlsec
-import (
- "errors"
- "unsafe"
-)
+import "unsafe"
// Note: on mac you need:
// brew install libxmlsec1 libxml2
@@ -30,7 +27,7 @@ import "C"
// }
import "C"
-// void onError_cgo(char *file, int line, char *funcName, char *errorObject, char *errorSubject, int reason, char *msg);
+// void captureXmlErrors();
import "C"
func init() {
@@ -46,26 +43,26 @@ func init() {
panic("xmlsec crypto initialization failed.")
}
- C.xmlSecErrorsSetCallback((C.xmlSecErrorsCallback)(unsafe.Pointer(C.onError_cgo)))
+ C.captureXmlErrors()
}
func newDoc(buf []byte, idattrs []XMLIDOption) (*C.xmlDoc, error) {
ctx := C.xmlCreateMemoryParserCtxt((*C.char)(unsafe.Pointer(&buf[0])),
C.int(len(buf)))
if ctx == nil {
- return nil, errors.New("error creating parser")
+ return nil, mustPopError()
}
defer C.xmlFreeParserCtxt(ctx)
C.xmlParseDocument(ctx)
if ctx.wellFormed == C.int(0) {
- return nil, errors.New("malformed XML")
+ return nil, mustPopError()
}
doc := ctx.myDoc
if doc == nil {
- return nil, errors.New("parse failed")
+ return nil, mustPopError()
}
for _, idattr := range idattrs {