swig-4.0.1-Fix-crash-in-Python-backend-when-using-empty-docstrings.patch 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. From e14532ce52a654768cc4010e9e18e1a0a4d965db Mon Sep 17 00:00:00 2001
  2. From: Vadim Zeitlin <vz-swig@zeitlins.org>
  3. Date: Sat, 25 Jan 2020 17:06:20 +0100
  4. Subject: [PATCH] Fix crash in Python backend when using empty docstrings
  5. Due to confusion in build_combined_docstring(), we could call
  6. DohDelete() on the "feature:docstring" string, which resulted in a crash
  7. when trying to use it later.
  8. Fix this and simplify the code at the same time by ensuring that we
  9. always use a copy of "feature:docstring" if it's not empty or don't use
  10. it at all if it's empty -- like this we don't have to check for its
  11. length each time before using it.
  12. Closes #1648.
  13. ---
  14. Examples/test-suite/autodoc.i | 9 +++++++++
  15. Examples/test-suite/python/autodoc_runme.py | 2 ++
  16. Source/Modules/python.cxx | 15 +++++++++++----
  17. 3 files changed, 22 insertions(+), 4 deletions(-)
  18. diff --git a/Examples/test-suite/autodoc.i b/Examples/test-suite/autodoc.i
  19. index 9f4365ee1c..efc7201553 100644
  20. --- a/Examples/test-suite/autodoc.i
  21. +++ b/Examples/test-suite/autodoc.i
  22. @@ -183,3 +183,12 @@ const int PROCESS_DEFAULT_VALUE = 17;
  23. typedef long int some_type;
  24. int process_complex_defval(int val = PROCESS_DEFAULT_VALUE, int factor = some_type(-1)) { return val*factor; }
  25. %}
  26. +
  27. +// Test for empty docstring, which should be ignored.
  28. +%feature("docstring") ""
  29. +
  30. +%inline %{
  31. +struct a_structure{
  32. + char my_array[1];
  33. +};
  34. +%}
  35. diff --git a/Examples/test-suite/python/autodoc_runme.py b/Examples/test-suite/python/autodoc_runme.py
  36. index 6002d49fec..7bc918644d 100644
  37. --- a/Examples/test-suite/python/autodoc_runme.py
  38. +++ b/Examples/test-suite/python/autodoc_runme.py
  39. @@ -279,3 +279,5 @@ def check(got, expected, expected_builtin=None, skip=False):
  40. check(inspect.getdoc(process4), "process4(int _from=0, int _in=1, int var=2) -> int")
  41. check(inspect.getdoc(process_complex_defval), "process_complex_defval(val=PROCESS_DEFAULT_VALUE, factor=some_type(-1)) -> int")
  42. +
  43. +check(inspect.getdoc(a_structure.__init__), "__init__(a_structure self) -> a_structure", None, skip)
  44. diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx
  45. index 1dbedad26a..f6b47be244 100644
  46. --- a/Source/Modules/python.cxx
  47. +++ b/Source/Modules/python.cxx
  48. @@ -1484,8 +1484,15 @@ class PYTHON:public Language {
  49. String *build_combined_docstring(Node *n, autodoc_t ad_type, const String *indent = "", bool low_level = false) {
  50. String *docstr = Getattr(n, "feature:docstring");
  51. - if (docstr && Len(docstr)) {
  52. - docstr = Copy(docstr);
  53. + if (docstr) {
  54. + // Simplify the code below by just ignoring empty docstrings.
  55. + if (!Len(docstr))
  56. + docstr = NULL;
  57. + else
  58. + docstr = Copy(docstr);
  59. + }
  60. +
  61. + if (docstr) {
  62. char *t = Char(docstr);
  63. if (*t == '{') {
  64. Delitem(docstr, 0);
  65. @@ -1496,7 +1503,7 @@ class PYTHON:public Language {
  66. if (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc")) {
  67. String *autodoc = make_autodoc(n, ad_type, low_level);
  68. if (autodoc && Len(autodoc) > 0) {
  69. - if (docstr && Len(docstr)) {
  70. + if (docstr) {
  71. Append(autodoc, "\n");
  72. Append(autodoc, docstr);
  73. }
  74. @@ -1509,7 +1516,7 @@ class PYTHON:public Language {
  75. Delete(autodoc);
  76. }
  77. - if (!docstr || !Len(docstr)) {
  78. + if (!docstr) {
  79. if (doxygen) {
  80. docstr = Getattr(n, "python:docstring");
  81. if (!docstr && doxygenTranslator->hasDocumentation(n)) {