From 5deeca06f5c0dbc25cc3c9fa11d4af4de22a23ed Mon Sep 17 00:00:00 2001
From: Dmitry Rodionov <d.rodionov@picodata.io>
Date: Thu, 25 Jan 2024 22:05:33 +0300
Subject: [PATCH] Pick up stat analysis patches made for 23.12 and 2.11.0

This patch combines patches from these two picodata/tarantool fork branches:
https://git.picodata.io/picodata/tarantool/-/tree/dynamic-linking-from-system?ref_type=heads
https://git.picodata.io/picodata/picodata/picodata/-/tree/svace-fixes?ref_type=heads

Previously patches for tarantool were made for 2.11.0 so for 2.11.2 (version we currently use)
some of them had to be updated.

Patches from b124e8f01fafb98bc3005f77b8852d1f699f8666 initially were committed
to fork repo but for manageability it was decided that its easier to support
those via patch files. So these changes are added to existing patches in
certification_patches dir.

Then follow changes from 6b851b86a20818981e28962a7ac2a0764b21b2d4
and 2be2aab5096b202de8bab72bafe41470c479895d. Patch application is
currently concentrated in gitlab-ci.yml. 6b851b moved svace patches
application to tarantool's makefile. For now its easier to keep it
in one place. Svace patches from previous commit are moved into
subdirectory. Patches that touch supplementary files or simply remove
them are removed and the list of the files is kept for later to form a
dedicated list of files for deletion.

Conflicting were picked from f98334ea66de2f61866cd33d97f1717738fc841b.
Redundant patch for curl libssh was removed because the same change
appeared upstream https://github.com/curl/curl/pull/11088/files

Luagdb patch was updated.
OSCP response patch as well as icu_common_exec patch were removed,
since original files are not needed in the build process and thus are
deleted from the repo.

Lastly patch application is moved to dedicated python script for
ease of sharing with vm builder repo.

Co-authored-by: Feodor Alexandrov <feodor.alex.alexandrov@gmail.com>
---
 .gitlab-ci.yml                                |  15 +--
 certification_patches/curl_libssh2.patch      |  17 ---
 .../checks_debian_prebuild.patch              |   0
 .../checks_rpm_prebuild.patch                 |   0
 .../curl_tool_dirhie.patch                    |   0
 .../curl_tool_getparam.patch                  |   0
 .../curl_tool_paramhlp.patch                  |   0
 .../http_debian_pribuild.patch                |   0
 .../http_rpm_prebuild.patch                   |   0
 .../luajit_luajit-gdb.patch                   |  10 +-
 .../nghttp2_mkhufftbl.patch                   |   0
 .../tarantool-sys_docker.patch                |   0
 .../tarantool-sys_icu_filtration.patch        |   0
 .../tarantool-sys_icu_makefile.patch          |   0
 .../tarantool-sys_icu_request_types.patch     |   0
 .../tarantool-sys_icu_utils.patch             |   0
 .../tarantool-sys_lua-cjson.patch             |  13 +++
 .../tarantool-sys_tarantool-gdb.patch         |   0
 .../vshard_debian_prebuild.patch              |   0
 .../vshard_rpm_prebuild.patch                 |   0
 .../zstd_freestanding.patch                   |   0
 .../nghttp2_fetch-ocsp-response.patch         |  22 ----
 .../svace_patches/luajit_lj_udata.patch       |  21 ++++
 .../svace_patches/luajit_minilua.patch        |  13 +++
 .../svace_patches/tarantool-sys_alter.patch   |  41 +++++++
 .../tarantool-sys_bps_tree.patch              |  12 ++
 .../svace_patches/tarantool-sys_build.patch   |  28 +++++
 .../svace_patches/tarantool-sys_eio.patch     |  35 ++++++
 .../svace_patches/tarantool-sys_ev.patch      |  72 ++++++++++++
 .../tarantool-sys_ev_iouring.patch            |  19 +++
 .../svace_patches/tarantool-sys_expr.patch    |  14 +++
 .../svace_patches/tarantool-sys_lemon.patch   |  19 +++
 .../svace_patches/tarantool-sys_say.patch     |  12 ++
 .../tarantool-sys_wherecode.patch             |  13 +++
 .../tarantool-sys_icu_common_exec.patch       |  24 ----
 .../prepare_source_tree_for_stat_analysis.py  | 110 ++++++++++++++++++
 36 files changed, 432 insertions(+), 78 deletions(-)
 delete mode 100644 certification_patches/curl_libssh2.patch
 rename certification_patches/{ => gamayun_patches}/checks_debian_prebuild.patch (100%)
 rename certification_patches/{ => gamayun_patches}/checks_rpm_prebuild.patch (100%)
 rename certification_patches/{ => gamayun_patches}/curl_tool_dirhie.patch (100%)
 rename certification_patches/{ => gamayun_patches}/curl_tool_getparam.patch (100%)
 rename certification_patches/{ => gamayun_patches}/curl_tool_paramhlp.patch (100%)
 rename certification_patches/{ => gamayun_patches}/http_debian_pribuild.patch (100%)
 rename certification_patches/{ => gamayun_patches}/http_rpm_prebuild.patch (100%)
 rename certification_patches/{ => gamayun_patches}/luajit_luajit-gdb.patch (50%)
 rename certification_patches/{ => gamayun_patches}/nghttp2_mkhufftbl.patch (100%)
 rename certification_patches/{ => gamayun_patches}/tarantool-sys_docker.patch (100%)
 rename certification_patches/{ => gamayun_patches}/tarantool-sys_icu_filtration.patch (100%)
 rename certification_patches/{ => gamayun_patches}/tarantool-sys_icu_makefile.patch (100%)
 rename certification_patches/{ => gamayun_patches}/tarantool-sys_icu_request_types.patch (100%)
 rename certification_patches/{ => gamayun_patches}/tarantool-sys_icu_utils.patch (100%)
 create mode 100644 certification_patches/gamayun_patches/tarantool-sys_lua-cjson.patch
 rename certification_patches/{ => gamayun_patches}/tarantool-sys_tarantool-gdb.patch (100%)
 rename certification_patches/{ => gamayun_patches}/vshard_debian_prebuild.patch (100%)
 rename certification_patches/{ => gamayun_patches}/vshard_rpm_prebuild.patch (100%)
 rename certification_patches/{ => gamayun_patches}/zstd_freestanding.patch (100%)
 delete mode 100644 certification_patches/nghttp2_fetch-ocsp-response.patch
 create mode 100644 certification_patches/svace_patches/luajit_lj_udata.patch
 create mode 100644 certification_patches/svace_patches/luajit_minilua.patch
 create mode 100644 certification_patches/svace_patches/tarantool-sys_alter.patch
 create mode 100644 certification_patches/svace_patches/tarantool-sys_bps_tree.patch
 create mode 100644 certification_patches/svace_patches/tarantool-sys_build.patch
 create mode 100644 certification_patches/svace_patches/tarantool-sys_eio.patch
 create mode 100644 certification_patches/svace_patches/tarantool-sys_ev.patch
 create mode 100644 certification_patches/svace_patches/tarantool-sys_ev_iouring.patch
 create mode 100644 certification_patches/svace_patches/tarantool-sys_expr.patch
 create mode 100644 certification_patches/svace_patches/tarantool-sys_lemon.patch
 create mode 100644 certification_patches/svace_patches/tarantool-sys_say.patch
 create mode 100644 certification_patches/svace_patches/tarantool-sys_wherecode.patch
 delete mode 100644 certification_patches/tarantool-sys_icu_common_exec.patch
 create mode 100755 tools/prepare_source_tree_for_stat_analysis.py

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index cd5fb2f3be..223dc66464 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -344,6 +344,8 @@ gamayun-run:
     - eval $TUNNEL
     - ls -la
     - |
+      # TODO consider moving this to the script as well, this may delete some html 
+      # license files which is probably not intended
       find . -type d -name 'test*' -o -name 'doc' -o -name 'docs' | xargs -n1 rm -rvf
       find tarantool-sys/third_party/ -type f -name '*.htm*' | xargs -n 1 rm -rfv
       find tarantool-sys/vendor/ -type f -name '*.htm*' | xargs -n 1 rm -rfv
@@ -353,20 +355,13 @@ gamayun-run:
       find . -type d -name 'docsrc' | xargs -n 1 rm -rvf
       find . -name '*.md' | xargs -n 1 rm -rvf
       find http tarantool-sys vshard -type d -name .github | xargs -n 1 rm -rfv
-    - PATCH_DIR=$(pwd)/certification_patches
     - |
-      (cd tarantool-sys; find ${PATCH_DIR} -name "tarantool-sys_*" | xargs -n 1 git apply)
-      (cd tarantool-sys/third_party/curl; find ${PATCH_DIR} -name "curl_*" | xargs -n 1 git apply)
-      (cd tarantool-sys/third_party/zstd; find ${PATCH_DIR} -name "zstd_*" | xargs -n 1 git apply)
-      (cd tarantool-sys/third_party/luajit; find ${PATCH_DIR} -name "luajit_*" | xargs -n 1 git apply)
-      (cd tarantool-sys/third_party/nghttp2; find ${PATCH_DIR} -name "nghttp2_*" | xargs -n 1 git apply)
-      (cd tarantool-sys/third_party/checks; find ${PATCH_DIR} -name "checks_*" | xargs -n 1 git apply)
-      (cd http; find ${PATCH_DIR} -name "http_*" | xargs -n 1 git apply)
-      (cd vshard; find ${PATCH_DIR} -name "vshard_*" | xargs -n 1 git apply)
+      ./tools/prepare_source_tree_for_stat_analysis.py gamayun
+      ./tools/prepare_source_tree_for_stat_analysis.py svace
     - |
       docker run --rm -t \
         -v $PWD:/tmp/src:rw \
-        -e "SONAR_OPS=-Dsonar.python.version=3 -Dsonar.login=${SONAR} -Dsonar.projectKey=Picodata-CI -Dsonar.exclusions=**/*.mod" \
+        -e "SONAR_OPS=-Dsonar.python.version=3 -Dsonar.login=${SONAR} -Dsonar.projectKey=Picodata-CI -Dsonar.exclusions=**/*.mod,osv-sonar.json" \
         -e "SONAR_SCANNER_OPTS="-Xmx4096m"" \
         -e "CARGO_CLIPPY_FILE=clippy.json" \
         -u $(id -u):$(id -g) --ulimit nofile=100000:100000 --network=host \
diff --git a/certification_patches/curl_libssh2.patch b/certification_patches/curl_libssh2.patch
deleted file mode 100644
index e9c14c91b0..0000000000
--- a/certification_patches/curl_libssh2.patch
+++ /dev/null
@@ -1,17 +0,0 @@
-diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c
-index ce9229f8f..4aef2ae70 100644
---- a/lib/vssh/libssh2.c
-+++ b/lib/vssh/libssh2.c
-@@ -723,11 +723,11 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
-      */
-     if((pub_pos != b64_pos) ||
-        strncmp(fingerprint_b64, pubkey_sha256, pub_pos)) {
--      free(fingerprint_b64);
- 
-       failf(data,
-             "Denied establishing ssh session: mismatch sha256 fingerprint. "
-             "Remote %s is not equal to %s", fingerprint_b64, pubkey_sha256);
-+      free(fingerprint_b64);
-       state(data, SSH_SESSION_FREE);
-       sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
-       return sshc->actualcode;
diff --git a/certification_patches/checks_debian_prebuild.patch b/certification_patches/gamayun_patches/checks_debian_prebuild.patch
similarity index 100%
rename from certification_patches/checks_debian_prebuild.patch
rename to certification_patches/gamayun_patches/checks_debian_prebuild.patch
diff --git a/certification_patches/checks_rpm_prebuild.patch b/certification_patches/gamayun_patches/checks_rpm_prebuild.patch
similarity index 100%
rename from certification_patches/checks_rpm_prebuild.patch
rename to certification_patches/gamayun_patches/checks_rpm_prebuild.patch
diff --git a/certification_patches/curl_tool_dirhie.patch b/certification_patches/gamayun_patches/curl_tool_dirhie.patch
similarity index 100%
rename from certification_patches/curl_tool_dirhie.patch
rename to certification_patches/gamayun_patches/curl_tool_dirhie.patch
diff --git a/certification_patches/curl_tool_getparam.patch b/certification_patches/gamayun_patches/curl_tool_getparam.patch
similarity index 100%
rename from certification_patches/curl_tool_getparam.patch
rename to certification_patches/gamayun_patches/curl_tool_getparam.patch
diff --git a/certification_patches/curl_tool_paramhlp.patch b/certification_patches/gamayun_patches/curl_tool_paramhlp.patch
similarity index 100%
rename from certification_patches/curl_tool_paramhlp.patch
rename to certification_patches/gamayun_patches/curl_tool_paramhlp.patch
diff --git a/certification_patches/http_debian_pribuild.patch b/certification_patches/gamayun_patches/http_debian_pribuild.patch
similarity index 100%
rename from certification_patches/http_debian_pribuild.patch
rename to certification_patches/gamayun_patches/http_debian_pribuild.patch
diff --git a/certification_patches/http_rpm_prebuild.patch b/certification_patches/gamayun_patches/http_rpm_prebuild.patch
similarity index 100%
rename from certification_patches/http_rpm_prebuild.patch
rename to certification_patches/gamayun_patches/http_rpm_prebuild.patch
diff --git a/certification_patches/luajit_luajit-gdb.patch b/certification_patches/gamayun_patches/luajit_luajit-gdb.patch
similarity index 50%
rename from certification_patches/luajit_luajit-gdb.patch
rename to certification_patches/gamayun_patches/luajit_luajit-gdb.patch
index bebb807a1a..0319d3f45f 100644
--- a/certification_patches/luajit_luajit-gdb.patch
+++ b/certification_patches/gamayun_patches/luajit_luajit-gdb.patch
@@ -1,14 +1,14 @@
 diff --git a/src/luajit-gdb.py b/src/luajit-gdb.py
-index 96ee2289..7fd90e88 100644
+index d2070e9b..05351b9f 100644
 --- a/src/luajit-gdb.py
 +++ b/src/luajit-gdb.py
-@@ -279,7 +279,8 @@ def itypemap(o):
-         return LJ_T['NUMX'] if tvisnumber(o) else itype(o)
+@@ -327,7 +327,8 @@ def itypemap(o):
+ 
  
  def funcproto(func):
--    assert(func['ffid'] == 0)
+-    assert func['ffid'] == 0
 +    if not (func['ffid'] == 0):
 +        raise RuntimeError("assert failed")
  
      return cast('GCproto *',
-         mref('char *', func['pc']) - gdb.lookup_type('GCproto').sizeof)
+                 mref('char *', func['pc']) - gdb.lookup_type('GCproto').sizeof)
diff --git a/certification_patches/nghttp2_mkhufftbl.patch b/certification_patches/gamayun_patches/nghttp2_mkhufftbl.patch
similarity index 100%
rename from certification_patches/nghttp2_mkhufftbl.patch
rename to certification_patches/gamayun_patches/nghttp2_mkhufftbl.patch
diff --git a/certification_patches/tarantool-sys_docker.patch b/certification_patches/gamayun_patches/tarantool-sys_docker.patch
similarity index 100%
rename from certification_patches/tarantool-sys_docker.patch
rename to certification_patches/gamayun_patches/tarantool-sys_docker.patch
diff --git a/certification_patches/tarantool-sys_icu_filtration.patch b/certification_patches/gamayun_patches/tarantool-sys_icu_filtration.patch
similarity index 100%
rename from certification_patches/tarantool-sys_icu_filtration.patch
rename to certification_patches/gamayun_patches/tarantool-sys_icu_filtration.patch
diff --git a/certification_patches/tarantool-sys_icu_makefile.patch b/certification_patches/gamayun_patches/tarantool-sys_icu_makefile.patch
similarity index 100%
rename from certification_patches/tarantool-sys_icu_makefile.patch
rename to certification_patches/gamayun_patches/tarantool-sys_icu_makefile.patch
diff --git a/certification_patches/tarantool-sys_icu_request_types.patch b/certification_patches/gamayun_patches/tarantool-sys_icu_request_types.patch
similarity index 100%
rename from certification_patches/tarantool-sys_icu_request_types.patch
rename to certification_patches/gamayun_patches/tarantool-sys_icu_request_types.patch
diff --git a/certification_patches/tarantool-sys_icu_utils.patch b/certification_patches/gamayun_patches/tarantool-sys_icu_utils.patch
similarity index 100%
rename from certification_patches/tarantool-sys_icu_utils.patch
rename to certification_patches/gamayun_patches/tarantool-sys_icu_utils.patch
diff --git a/certification_patches/gamayun_patches/tarantool-sys_lua-cjson.patch b/certification_patches/gamayun_patches/tarantool-sys_lua-cjson.patch
new file mode 100644
index 0000000000..c669ded163
--- /dev/null
+++ b/certification_patches/gamayun_patches/tarantool-sys_lua-cjson.patch
@@ -0,0 +1,13 @@
+diff --git a/third_party/lua-cjson/strbuf.c b/third_party/lua-cjson/strbuf.c
+index 69057ffb3..5a0272be1 100644
+--- a/third_party/lua-cjson/strbuf.c
++++ b/third_party/lua-cjson/strbuf.c
+@@ -106,7 +106,7 @@ static int calculate_new_size(strbuf_t *s, int len)
+         /* Exponential sizing */
+         while (newsize < reqsize)
+             newsize *= -s->increment;
+-    } else {
++    } else if (s->increment > 0) {
+         /* Linear sizing */
+         newsize = ((newsize + s->increment - 1) / s->increment) * s->increment;
+     }
diff --git a/certification_patches/tarantool-sys_tarantool-gdb.patch b/certification_patches/gamayun_patches/tarantool-sys_tarantool-gdb.patch
similarity index 100%
rename from certification_patches/tarantool-sys_tarantool-gdb.patch
rename to certification_patches/gamayun_patches/tarantool-sys_tarantool-gdb.patch
diff --git a/certification_patches/vshard_debian_prebuild.patch b/certification_patches/gamayun_patches/vshard_debian_prebuild.patch
similarity index 100%
rename from certification_patches/vshard_debian_prebuild.patch
rename to certification_patches/gamayun_patches/vshard_debian_prebuild.patch
diff --git a/certification_patches/vshard_rpm_prebuild.patch b/certification_patches/gamayun_patches/vshard_rpm_prebuild.patch
similarity index 100%
rename from certification_patches/vshard_rpm_prebuild.patch
rename to certification_patches/gamayun_patches/vshard_rpm_prebuild.patch
diff --git a/certification_patches/zstd_freestanding.patch b/certification_patches/gamayun_patches/zstd_freestanding.patch
similarity index 100%
rename from certification_patches/zstd_freestanding.patch
rename to certification_patches/gamayun_patches/zstd_freestanding.patch
diff --git a/certification_patches/nghttp2_fetch-ocsp-response.patch b/certification_patches/nghttp2_fetch-ocsp-response.patch
deleted file mode 100644
index 95a2215c59..0000000000
--- a/certification_patches/nghttp2_fetch-ocsp-response.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-diff --git a/script/fetch-ocsp-response b/script/fetch-ocsp-response
-index 0ff7461e..2fb75c40 100755
---- a/script/fetch-ocsp-response
-+++ b/script/fetch-ocsp-response
-@@ -83,7 +83,7 @@ def tempfail(msg):
- def run_openssl(args, allow_tempfail=False):
-     buf = io.BytesIO()
-     try:
--        p = subprocess.Popen(args, stdout=subprocess.PIPE)
-+        p = subprocess.Popen(args, stdout=subprocess.PIPE)  # nosec
-     except Exception as e:
-         die('failed to invoke {}:{}'.format(args, e))
-     try:
-@@ -172,7 +172,7 @@ def verify_response(cmd, tempdir, issuer_fn, respder_fn):
-         with open(verify_fn, 'w+b') as f:
-             args = [cmd, 'ocsp', '-respin', respder_fn]
-             args.extend(extra)
--            p = subprocess.Popen(args, stdout=f, stderr=f)
-+            p = subprocess.Popen(args, stdout=f, stderr=f)  # nosec
-             if p.wait() == 0:
-                 # OpenSSL <= 1.0.1, openssl ocsp still returns exit
-                 # code 0 even if verification was failed.  So check
diff --git a/certification_patches/svace_patches/luajit_lj_udata.patch b/certification_patches/svace_patches/luajit_lj_udata.patch
new file mode 100644
index 0000000000..82723902b9
--- /dev/null
+++ b/certification_patches/svace_patches/luajit_lj_udata.patch
@@ -0,0 +1,21 @@
+diff --git a/src/lj_udata.c b/src/lj_udata.c
+index 1b7841fa..22426dbb 100644
+--- a/src/lj_udata.c
++++ b/src/lj_udata.c
+@@ -6,6 +6,8 @@
+ #define lj_udata_c
+ #define LUA_CORE
+ 
++#include <assert.h>
++
+ #include "lj_obj.h"
+ #include "lj_gc.h"
+ #include "lj_err.h"
+@@ -57,6 +59,7 @@ void *lj_lightud_intern(lua_State *L, void *p)
+     setmref(g->gc.lightudseg, segmap);
+   }
+   g->gc.lightudnum = segnum;
++  assert(segmap != NULL);
+   segmap[segnum] = up;
+   return (void *)(((uint64_t)segnum << LJ_LIGHTUD_BITS_LO) | lightudlo(u));
+ }
diff --git a/certification_patches/svace_patches/luajit_minilua.patch b/certification_patches/svace_patches/luajit_minilua.patch
new file mode 100644
index 0000000000..2566ca4869
--- /dev/null
+++ b/certification_patches/svace_patches/luajit_minilua.patch
@@ -0,0 +1,13 @@
+diff --git a/src/host/minilua.c b/src/host/minilua.c
+index 79150286..33b5ab51 100644
+--- a/src/host/minilua.c
++++ b/src/host/minilua.c
+@@ -4327,7 +4327,7 @@ if(lh->v.u.s.info==v->u.s.info){
+ conflict=1;
+ lh->v.u.s.info=extra;
+ }
+-if(lh->v.u.s.aux==v->u.s.info){
++if(lh->v.u.s.aux==v->u.s.aux){
+ conflict=1;
+ lh->v.u.s.aux=extra;
+ }
diff --git a/certification_patches/svace_patches/tarantool-sys_alter.patch b/certification_patches/svace_patches/tarantool-sys_alter.patch
new file mode 100644
index 0000000000..b927e90639
--- /dev/null
+++ b/certification_patches/svace_patches/tarantool-sys_alter.patch
@@ -0,0 +1,41 @@
+diff --git a/src/box/alter.cc b/src/box/alter.cc
+index 7aeab4648..7b8cd489c 100644
+--- a/src/box/alter.cc
++++ b/src/box/alter.cc
+@@ -1774,6 +1774,7 @@ alter_space_move_indexes(struct alter_space *alter, uint32_t begin,
+ 					old_def->name, strlen(old_def->name),
+ 					old_def->type, &old_def->opts,
+ 					old_def->key_def, alter->pk_def);
++		assert(new_def != NULL);
+ 		index_def_update_optionality(new_def, min_field_count);
+ 		auto guard = make_scoped_guard([=] { index_def_delete(new_def); });
+ 		if (!index_def_change_requires_rebuild(old_index, new_def))
+@@ -2996,6 +2997,8 @@ on_replace_dd_user(struct trigger * /* trigger */, void *event)
+ 			return -1;
+ 		txn_stmt_on_rollback(stmt, on_rollback);
+ 	} else if (new_tuple == NULL) { /* DELETE */
++		if (old_user == NULL)
++			return -1; /* using if instead of assert for svace */
+ 		if (access_check_ddl(old_user->def->name, old_user->def->uid,
+ 				 old_user->def->owner, old_user->def->type,
+ 				 BOX_PRIVILEGE_DROP) != 0)
+@@ -3353,6 +3356,8 @@ on_replace_dd_func(struct trigger * /* trigger */, void *event)
+ 		if (trigger_run(&on_alter_func, func) != 0)
+ 			return -1;
+ 	} else if (new_tuple == NULL) {         /* DELETE */
++		if (old_func == NULL)
++			return -1; /* using if instead of assert for svace */
+ 		uint32_t uid;
+ 		if (func_def_get_ids_from_tuple(old_tuple, &fid, &uid) != 0)
+ 			return -1;
+@@ -4392,7 +4397,9 @@ on_replace_dd_sequence(struct trigger * /* trigger */, void *event)
+ 		sequence_cache_delete(seq->def->id);
+ 		txn_stmt_on_commit(stmt, on_commit);
+ 		txn_stmt_on_rollback(stmt, on_rollback);
+-	} else {						/* UPDATE */
++	} else {
++		if (new_tuple == NULL)			/* UPDATE */
++			return -1; /* using if instead of assert for svace */
+ 		new_def = sequence_def_new_from_tuple(new_tuple,
+ 						      ER_ALTER_SEQUENCE);
+ 		if (new_def == NULL)
diff --git a/certification_patches/svace_patches/tarantool-sys_bps_tree.patch b/certification_patches/svace_patches/tarantool-sys_bps_tree.patch
new file mode 100644
index 0000000000..b43b55e89c
--- /dev/null
+++ b/certification_patches/svace_patches/tarantool-sys_bps_tree.patch
@@ -0,0 +1,12 @@
+diff --git a/src/lib/salad/bps_tree.h b/src/lib/salad/bps_tree.h
+index e340588cb..7cdeb9770 100644
+--- a/src/lib/salad/bps_tree.h
++++ b/src/lib/salad/bps_tree.h
+@@ -1585,6 +1585,7 @@ bps_tree_random(const struct bps_tree *t, size_t rnd)
+ 	for (bps_tree_block_id_t i = 0; i < tree->depth - 1; i++) {
+ 		struct bps_inner *inner = (struct bps_inner *)block;
+ 		bps_tree_pos_t pos = rnd % inner->header.size;
++		assert(pos < BPS_TREE_MAX_COUNT_IN_INNER);
+ 		rnd /= inner->header.size;
+ 		block = bps_tree_restore_block(tree, inner->child_ids[pos]);
+ 	}
diff --git a/certification_patches/svace_patches/tarantool-sys_build.patch b/certification_patches/svace_patches/tarantool-sys_build.patch
new file mode 100644
index 0000000000..d5ba95e20b
--- /dev/null
+++ b/certification_patches/svace_patches/tarantool-sys_build.patch
@@ -0,0 +1,28 @@
+diff --git a/src/box/sql/build.c b/src/box/sql/build.c
+index 6891de805..78428e9f9 100644
+--- a/src/box/sql/build.c
++++ b/src/box/sql/build.c
+@@ -1300,7 +1300,13 @@ vdbe_emit_create_constraints(struct Parse *parse, int reg_space_id)
+ 	 */
+ 	if (is_alter) {
+ 		space = parse->create_column_def.space;
+-		i = space_by_name(space->def->name)->index_count;
++		struct space *space_obj = space_by_name(space->def->name);
++		if (space_obj == NULL) {
++			diag_set(ClientError, ER_NO_SUCH_SPACE, space->def->name);
++			parse->is_aborted = true;
++			return;
++		}
++		i = space_obj->index_count;
+ 	}
+ 	assert(space != NULL);
+ 	for (; i < space->index_count; ++i) {
+@@ -2098,7 +2104,7 @@ sql_create_foreign_key(struct Parse *parse_context)
+ 					 constraint_name) != 0)
+ 				goto exit_create_fk;
+ 		/* In case of ALTER parent table must exist. */
+-		} else if (columnno_by_name(parse_context, child_space,
++		} else if (child_cols && columnno_by_name(parse_context, child_space,
+ 					    child_cols->a[i].zName,
+ 					    &fk_def->links[i].child_field,
+ 					    constraint_name) != 0) {
diff --git a/certification_patches/svace_patches/tarantool-sys_eio.patch b/certification_patches/svace_patches/tarantool-sys_eio.patch
new file mode 100644
index 0000000000..151d81134a
--- /dev/null
+++ b/certification_patches/svace_patches/tarantool-sys_eio.patch
@@ -0,0 +1,35 @@
+diff --git a/third_party/libeio/eio.c b/third_party/libeio/eio.c
+index 7351d5dda..513ac2461 100644
+--- a/third_party/libeio/eio.c
++++ b/third_party/libeio/eio.c
+@@ -1128,7 +1128,7 @@ eio__realpath (struct etp_tmpbuf *tmpbuf, eio_wd wd, const char *path)
+             /* we need to be careful, as rel might point into tmp2 already */
+             memmove (tmp2 + linklen + 1, rel, rellen + 1);
+             tmp2 [linklen] = '/';
+-            memcpy (tmp2, tmp1, linklen);
++            memmove (tmp2, tmp1, linklen);
+ 
+             rel = tmp2;
+           }
+@@ -1408,8 +1408,12 @@ eio__scandir (eio_req *req, etp_worker *self)
+   req->ptr1 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0;
+   req->ptr2 = names = malloc (namesalloc);
+ 
+-  if (!names || (flags && !dents))
++  if (!names || (flags && !dents)) {
++#ifndef _WIN32
++    closedir (dirp);
++#endif
+     return;
++  }
+ 
+   for (;;)
+     {
+@@ -2250,6 +2254,7 @@ eio__2path (int type, const char *path, const char *new_path, int pri, eio_cb cb
+   req->ptr2 = strdup (new_path);
+   if (!req->ptr2)
+     {
++      free(req->ptr1);
+       eio_api_destroy (req);
+       return 0;
+     }
diff --git a/certification_patches/svace_patches/tarantool-sys_ev.patch b/certification_patches/svace_patches/tarantool-sys_ev.patch
new file mode 100644
index 0000000000..b6e9e10cac
--- /dev/null
+++ b/certification_patches/svace_patches/tarantool-sys_ev.patch
@@ -0,0 +1,72 @@
+diff --git a/third_party/libev/ev.c b/third_party/libev/ev.c
+index 04119bf98..b46a8f324 100644
+--- a/third_party/libev/ev.c
++++ b/third_party/libev/ev.c
+@@ -2264,10 +2264,12 @@ array_nextsize (int elem, int cur, int cnt)
+     ncur <<= 1;
+   while (cnt > ncur);
+ 
++  assert((unsigned long)elem * (unsigned long)ncur <= INT_MAX);
+   /* if size is large, round to MALLOC_ROUND - 4 * longs to accommodate malloc overhead */
+-  if (elem * ncur > MALLOC_ROUND - sizeof (void *) * 4)
++  if ((unsigned long)elem * (unsigned long)ncur > MALLOC_ROUND - sizeof (void *) * 4)
+     {
+       ncur *= elem;
++      assert(((unsigned long)ncur + (unsigned long)elem + ((unsigned long)(MALLOC_ROUND - 1)) + sizeof (void *) * 4) <= INT_MAX);
+       ncur = (ncur + elem + (MALLOC_ROUND - 1) + sizeof (void *) * 4) & ~(MALLOC_ROUND - 1);
+       ncur = ncur - sizeof (void *) * 4;
+       ncur /= elem;
+@@ -2281,7 +2283,7 @@ static void *
+ array_realloc (int elem, void *base, int *cur, int cnt)
+ {
+   *cur = array_nextsize (elem, *cur, cnt);
+-  return ev_realloc (base, elem * *cur);
++  return ev_realloc (base, (long)elem * ((long)(*cur)));
+ }
+ 
+ #define array_needsize_noinit(base,offset,count)
+@@ -2852,7 +2854,13 @@ pipecb (EV_P_ ev_io *iow, int revents)
+       if (evpipe [0] < 0)
+         {
+           uint64_t counter;
+-          read (evpipe [1], &counter, sizeof (uint64_t));
++          ssize_t bytes_read = read (evpipe [1], &counter, sizeof (uint64_t));
++          if (bytes_read < 0) {
++            ev_syserr("(libev) error reading signal/async pipe");
++
++          } else if (bytes_read != sizeof (uint64_t)) {
++            ev_syserr("(libev) error not full reading signal/async pipe");
++          }
+         }
+       else
+ #endif
+@@ -2866,7 +2874,13 @@ pipecb (EV_P_ ev_io *iow, int revents)
+           buf.len = sizeof (dummy);
+           WSARecv (EV_FD_TO_WIN32_HANDLE (evpipe [0]), &buf, 1, &recvd, &flags, 0, 0);
+ #else
+-          read (evpipe [0], &dummy, sizeof (dummy));
++          ssize_t bytes_read = read (evpipe [0], &dummy, sizeof (dummy));
++          if (bytes_read < 0) {
++            ev_syserr("(libev) error reading signal/async pipe");
++
++          } else if (bytes_read != sizeof (dummy)) {
++            ev_syserr("(libev) error not full reading signal/async pipe");
++          }
+ #endif
+         }
+     }
+@@ -3299,10 +3313,12 @@ loop_init (EV_P_ unsigned int flags) EV_NOEXCEPT
+         curpid = getpid ();
+ #endif
+ 
++      char *env = getenv ("LIBEV_FLAGS");
++
+       if (!(flags & EVFLAG_NOENV)
+           && !enable_secure ()
+-          && getenv ("LIBEV_FLAGS"))
+-        flags = atoi (getenv ("LIBEV_FLAGS"));
++          && env != NULL)
++        flags = atoi (env);
+ 
+       ev_rt_now          = ev_time ();
+       mn_now             = get_clock ();
diff --git a/certification_patches/svace_patches/tarantool-sys_ev_iouring.patch b/certification_patches/svace_patches/tarantool-sys_ev_iouring.patch
new file mode 100644
index 0000000000..950e535f66
--- /dev/null
+++ b/certification_patches/svace_patches/tarantool-sys_ev_iouring.patch
@@ -0,0 +1,19 @@
+diff --git a/third_party/libev/ev_iouring.c b/third_party/libev/ev_iouring.c
+index 23788ea24..e47942e19 100644
+--- a/third_party/libev/ev_iouring.c
++++ b/third_party/libev/ev_iouring.c
+@@ -351,8 +351,12 @@ ecb_cold
+ static int
+ iouring_internal_destroy (EV_P)
+ {
+-  close (iouring_tfd);
+-  close (iouring_fd);
++  if (iouring_tfd > 0) {
++    close (iouring_tfd);
++  }
++  if (iouring_fd > 0) {
++    close (iouring_fd);
++  }
+ 
+   if (iouring_ring != MAP_FAILED) munmap (iouring_ring, iouring_ring_size);
+   if (iouring_sqes != MAP_FAILED) munmap (iouring_sqes, iouring_sqes_size);
diff --git a/certification_patches/svace_patches/tarantool-sys_expr.patch b/certification_patches/svace_patches/tarantool-sys_expr.patch
new file mode 100644
index 0000000000..4ff1844f28
--- /dev/null
+++ b/certification_patches/svace_patches/tarantool-sys_expr.patch
@@ -0,0 +1,14 @@
+diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
+index 3a2426bcd..4865f7865 100644
+--- a/src/box/sql/expr.c
++++ b/src/box/sql/expr.c
+@@ -1879,7 +1879,8 @@ sqlExprListSetName(Parse * pParse,	/* Parsing context */
+ 	} else {
+ 		item->zName = sql_xstrndup(pName->z, pName->n);
+ 	}
+-	sqlCheckIdentifierName(pParse, item->zName);
++	if (sqlCheckIdentifierName(pParse, item->zName) < 0)
++		sql_xfree(item->zName);
+ }
+ 
+ void
diff --git a/certification_patches/svace_patches/tarantool-sys_lemon.patch b/certification_patches/svace_patches/tarantool-sys_lemon.patch
new file mode 100644
index 0000000000..762c7a06e5
--- /dev/null
+++ b/certification_patches/svace_patches/tarantool-sys_lemon.patch
@@ -0,0 +1,19 @@
+diff --git a/extra/lemon.c b/extra/lemon.c
+index f5450ef83..8d5242617 100644
+--- a/extra/lemon.c
++++ b/extra/lemon.c
+@@ -1876,9 +1876,11 @@ static FILE *errstream;
+ */
+ static void errline(int n, int k, FILE *err)
+ {
+-  int spcnt, i;
+-  if( argv[0] ) fprintf(err,"%s",argv[0]);
+-  spcnt = lemonStrlen(argv[0]) + 1;
++  int spcnt = 0, i;
++  if( argv[0] ) {
++    fprintf(err,"%s",argv[0]);
++    spcnt = lemonStrlen(argv[0]) + 1;
++  }
+   for(i=1; i<n && argv[i]; i++){
+     fprintf(err," %s",argv[i]);
+     spcnt += lemonStrlen(argv[i])+1;
diff --git a/certification_patches/svace_patches/tarantool-sys_say.patch b/certification_patches/svace_patches/tarantool-sys_say.patch
new file mode 100644
index 0000000000..b105ba7302
--- /dev/null
+++ b/certification_patches/svace_patches/tarantool-sys_say.patch
@@ -0,0 +1,12 @@
+diff --git a/src/lib/core/say.c b/src/lib/core/say.c
+index a80880724..2ab3d5478 100644
+--- a/src/lib/core/say.c
++++ b/src/lib/core/say.c
+@@ -655,6 +655,7 @@ log_syslog_init(struct log *log, const char *init_str)
+ 	else
+ 		log->syslog_ident = strdup(opts.identity);
+ 	if (log->syslog_ident == NULL) {
++		assert(opts.identity != NULL);
+ 		diag_set(OutOfMemory, strlen(opts.identity), "malloc",
+ 		         "log->syslog_ident");
+ 		return -1;
diff --git a/certification_patches/svace_patches/tarantool-sys_wherecode.patch b/certification_patches/svace_patches/tarantool-sys_wherecode.patch
new file mode 100644
index 0000000000..7bbb4a51df
--- /dev/null
+++ b/certification_patches/svace_patches/tarantool-sys_wherecode.patch
@@ -0,0 +1,13 @@
+diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
+index 8cac15123..5f084394f 100644
+--- a/src/box/sql/wherecode.c
++++ b/src/box/sql/wherecode.c
+@@ -458,7 +458,7 @@ codeEqualityTerm(Parse * pParse,	/* The parsing context */
+ 			 * such a vector, some of the subroutines do not handle
+ 			 * this case.
+ 			 */
+-			if (pLhs->nExpr == 1) {
++			if (pLhs && pLhs->nExpr == 1) {
+ 				pX->pLeft = pLhs->a[0].pExpr;
+ 			} else {
+ 				pLeft->x.pList = pLhs;
diff --git a/certification_patches/tarantool-sys_icu_common_exec.patch b/certification_patches/tarantool-sys_icu_common_exec.patch
deleted file mode 100644
index 326b8d8d3a..0000000000
--- a/certification_patches/tarantool-sys_icu_common_exec.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-diff --git a/vendor/icu4c-71_1/source/python/icutools/databuilder/renderers/common_exec.py b/vendor/icu4c-71_1/source/python/icutools/databuilder/renderers/common_exec.py
-index 91c12fdcf..173bd0216 100644
---- a/vendor/icu4c-71_1/source/python/icutools/databuilder/renderers/common_exec.py
-+++ b/vendor/icu4c-71_1/source/python/icutools/databuilder/renderers/common_exec.py
-@@ -68,7 +68,8 @@ def run_helper(request, common_vars, platform, tool_dir, verbose, tool_cfg=None,
-         # No-op
-         return 0
- 
--    assert isinstance(request.tool, IcuTool)
-+    if not (isinstance(request.tool, IcuTool)):
-+        raise RuntimeError("assert failed")
-     if platform == "windows":
-         cmd_template = "{TOOL_DIR}/{TOOL}/{TOOL_CFG}/{TOOL}.exe {{ARGS}}".format(
-             TOOL_DIR = tool_dir,
-@@ -117,7 +118,8 @@ def run_helper(request, common_vars, platform, tool_dir, verbose, tool_cfg=None,
-             command_line = command_line.replace("/", "\\")
-         returncode = run_shell_command(command_line, platform, verbose)
-         return returncode
--    assert False
-+    if not (False):
-+        raise RuntimeError("assert failed")
- 
- def run_shell_command(command_line, platform, verbose):
-     changed_windows_comspec = False
diff --git a/tools/prepare_source_tree_for_stat_analysis.py b/tools/prepare_source_tree_for_stat_analysis.py
new file mode 100755
index 0000000000..93651821a9
--- /dev/null
+++ b/tools/prepare_source_tree_for_stat_analysis.py
@@ -0,0 +1,110 @@
+#!/usr/bin/env python3
+
+import argparse
+from contextlib import contextmanager
+import glob
+import os
+from pathlib import Path
+import subprocess  # nosec
+import sys
+
+REPO_DIR = Path(__file__).parent.parent
+PATCHES_DIR = REPO_DIR / "certification_patches"
+SVACE_PATCHES = PATCHES_DIR / "svace_patches"
+GAMAYUN_PATCHES = PATCHES_DIR / "gamayun_patches"
+TARANTOOL_SYS = REPO_DIR / "tarantool-sys"
+THIRD_PARTY = TARANTOOL_SYS / "third_party"
+
+DEBUG = os.getenv("DEBUG")
+
+# List of files that need to be deleted before stat analysis
+# Usually these are supplementary files from third party libraries
+# like test data, utility scripts etc.
+# This is needed because we cant use exclusion rules for static
+# analysis tools so we need to remove unwanted files from the artifact
+DEAD_LIST = [
+    # from 6b2a88b551e6940089cf248d88b050b65ab67262
+    "tarantool-sys/vendor/icu4c-71_1/source/python/icutools/databuilder/renderers/common_exec.py",
+    "tarantool-sys/third_party/nghttp2/script/fetch-ocsp-response",
+    "tarantool-sys/vendor/openssl-1.1.1q/fuzz/helper.py",
+    "tarantool-sys/third_party/zstd/.circleci/images/primary/Dockerfile",
+    # from 2be2aab5096b202de8bab72bafe41470c479895d
+    "tarantool-sys/third_party/nghttp2/src/ca.nghttp2.org-key.pem",
+    "tarantool-sys/third_party/nghttp2/src/ca.nghttp2.org.pem",
+    "tarantool-sys/third_party/nghttp2/src/test.example.com-key.pem",
+    "tarantool-sys/third_party/nghttp2/src/test.example.com.pem",
+    "tarantool-sys/third_party/nghttp2/src/test.nghttp2.org-key.pem",
+    "tarantool-sys/third_party/nghttp2/src/test.nghttp2.org.pem",
+    "tarantool-sys/third_party/curl/packages/OS400/initscript.sh",
+    "tarantool-sys/third_party/decNumber/example*.c",
+    "tarantool-sys/third_party/libeio/install-sh",
+    "tarantool-sys/third_party/libeio/ltmain.sh",
+    "tarantool-sys/third_party/libev/depcomp",
+    "tarantool-sys/third_party/libev/install-sh",
+    "tarantool-sys/third_party/libev/ltmain.sh",
+    "tarantool-sys/tools/gen-release-notes",
+    "sbroad/docker-compose.yml",
+]
+
+
+@contextmanager
+def cd(target: Path):
+    old = os.getcwd()
+    os.chdir(target)
+    yield
+    os.chdir(old)
+
+
+def apply(patch: Path):
+    subprocess.check_call(["git", "apply", str(patch)])  # nosec
+
+
+def apply_from_dir(path: Path):
+    for patch in path.iterdir():
+        patch = patch.resolve()
+        print("Applying:", patch)
+
+        libname = patch.stem.split("_", maxsplit=1)[0]
+
+        if libname == "tarantool-sys":
+            with cd(TARANTOOL_SYS):
+                apply(patch)
+        elif libname in ("http", "vshard"):
+            with cd(libname):
+                apply(patch)
+        else:
+            with cd(THIRD_PARTY / libname):
+                apply(patch)
+
+
+def prepare_for_gamayun():
+    for glob_pattern in DEAD_LIST:
+        for fname in glob.glob(glob_pattern):
+            print("Removing:", REPO_DIR / fname)
+
+            (REPO_DIR / fname).unlink(missing_ok=DEBUG)
+
+    apply_from_dir(GAMAYUN_PATCHES)
+
+
+def prepare_for_svace():
+    apply_from_dir(SVACE_PATCHES)
+
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser(
+        "Apply various certification induced transformations to source tree"
+    )
+    subparsers = parser.add_subparsers(dest="command")
+    subparsers.add_parser("gamayun", help="Prepare for gamayun analysis")
+    subparsers.add_parser("svace", help="Prepare for svace analysis")
+
+    commands = {"gamayun": prepare_for_gamayun, "svace": prepare_for_svace}
+
+    args = parser.parse_args()
+    command = commands.get(args.command)
+    if command is None:
+        print(f"Unknown command: {command}", file=sys.stderr)
+        sys.exit(1)
+
+    command()
-- 
GitLab