Repository: SINTEF/dlite (language: python)

Issue:
Misspelling of shape in the datamodel may cause DLite to crash
To reproduce the segfault, uncomment the two last lines in the following code segment at end of bindings/python/tests/test_entity.py:

```python
# Test loading invalid json input
with dlite.errctl(hide=True):
    Invalid1 = dlite.get_instance("http://onto-ns.com/meta/0.1/Invalid1")
with raises(dlite.DLiteMissingInstanceError, dlite.DLiteSyntaxError):
    invalid1 = Invalid1([2], properties={"name": "a", "f": [3.14, 2.72]})

# For issue #686. Uncommenting the two last lines will result in segfault
Invalid2 = dlite.get_instance("http://onto-ns.com/meta/0.1/Invalid2")
#with raises(dlite.DLiteMissingInstanceError, dlite.DLiteSyntaxError):
#    invalid2 = Invalid2([2])
```

It seems that the segfault is related to invalid shape name of a 'ref' type property, since Invalid1 produces an expected exception instead of causing a segfault.

Added test utilities
# Description
Replaced pytest.raises() with an own implementation. Another benefit is that it silence expected DLite error messages written to stderr.

Also removed some unused imports in swig interface. OrderedDict is not longer needed after Python 3.7, which is the lowest version of Python supported by DLite.

Alse allowed dlite.errctl() hide and show arguments to be boolean (for convenience).

Also added some extra tests to reproduce a segfault (issue #686). 

## Type of change
- [x] Bug fix & code cleanup
- [ ] New feature
- [ ] Documentation update
- [x] Test update

## Checklist for the reviewer
This checklist should be used as a help for the reviewer.

- [ ] Is the change limited to one issue?
- [ ] Does this PR close the issue?
- [ ] Is the code easy to read and understand?
- [ ] Do all new feature have an accompanying new test?
- [ ] Has the documentation been updated as necessary?



Discussion / hints:

Fix patch:
diff --git a/src/dlite-entity.c b/src/dlite-entity.c
index 2ca18cddc..e2353c673 100644
--- a/src/dlite-entity.c
+++ b/src/dlite-entity.c
@@ -577,10 +577,12 @@ static int dlite_instance_free(DLiteInstance *inst)
         if (dlite_type_is_allocated(p->type)) {
           int j;
           size_t n, nmemb=1;
+          char *memptr = *(char **)ptr;
           for (j=0; j<p->ndims; j++)
             nmemb *= DLITE_PROP_DIM(inst, i, j);
-          for (n=0; n<nmemb; n++)
-            dlite_type_clear(*(char **)ptr + n*p->size, p->type, p->size);
+          if (memptr)
+            for (n=0; n<nmemb; n++)
+              dlite_type_clear(memptr + n*p->size, p->type, p->size);
         }
         free(*(void **)ptr);
       } else {


Test patch:
diff --git a/bindings/python/tests/test_entity.py b/bindings/python/tests/test_entity.py
index eb0598682..87af26011 100755
--- a/bindings/python/tests/test_entity.py
+++ b/bindings/python/tests/test_entity.py
@@ -314,7 +314,8 @@
 with raises(dlite.DLiteMissingInstanceError, dlite.DLiteSyntaxError):
     invalid1 = Invalid1([2], properties={"name": "a", "f": [3.14, 2.72]})
 
-# For issue #686. Uncommenting the two last lines will result in segfault
+
+# For issue #686
 Invalid2 = dlite.get_instance("http://onto-ns.com/meta/0.1/Invalid2")
-#with raises(dlite.DLiteMissingInstanceError, dlite.DLiteSyntaxError):
-#    invalid2 = Invalid2([2])
+with raises(dlite.DLiteMissingInstanceError, dlite.DLiteSyntaxError):
+    invalid2 = Invalid2([2])