- Introduce the following new methods: * `rz_analysis_similarity_basic_block()` * `rz_analysis_similarity_function()` * `rz_analysis_similarity_basic_block_2()` * `rz_analysis_similarity_function_2()` * `rz_analysis_match_basic_blocks()` * `rz_analysis_match_functions()` * `rz_analysis_match_basic_blocks_2()` * `rz_analysis_match_functions_2()` - Remove `RzAnalysisDiff` and its usages - Remove `librz/analysis/diff.c` entirely to and adds `librz/analysis/similarity.c` - Remove a lot of unused structures and simplified the code by a lot - Fix typo in levenshtein - Remove `librz/core/gdiff.c` and `gdiff` functions since they were unused or only used in rz-diff - Remove `difftype` (or "color") from `RzANode` which lead to dead code - Decrease serialized data in projects. - Add `RzAnalysisVarKind` and `RzAnalysisVarType` and replaces all the hardcoded values - Remove command `agd` - Remove all `rz_core_gdiff` usages from `rz_core.h` - Refactor `rz_analysis_var_list` and `rz_analysis_var_count` due unused argument (`RzAnalysis` was not used) - Add new method `rz_analysis_var_count_total` to simplify some usages - Remove `rz_core_graph_diff` - Add `typedef RzAnalysisFcnType` on `enum``used for function types - Remove unused `RZ_ANALYSIS_FCN_VARKIND_LOCAL` - Remove from `RzAnalysisFunction` the following variables: * `fingerprint` * `fingerprint_size` * `diff` * `diff_ops` * `diff_thbb` * `diff_thfcn` - Remove from `RzAnalysisBlock` the following variables: * `fingerprint` * `diff` - Remove `RZ_ANALYSIS_THRESHOLDBB` and `RZ_ANALYSIS_THRESHOLDFCN` - Remove the following callbacks from `RzAnalysisPlugin` * `RzAnalysisDiffBBCallback` * `RzAnalysisDiffFcnCallback` * `RzAnalysisDiffEvalCallback` - Fix fancy table columns/rows when a color string is in a cell - Bumped project version to 9
114 lines
3 KiB
C
114 lines
3 KiB
C
// SPDX-FileCopyrightText: 2017 Fangrui Song <i@maskray.me>
|
|
// SPDX-FileCopyrightText: 2016 NikolaiHampton <nikolaih@3583bytesready.net>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
#include <rz_diff.h>
|
|
#include <rz_util/rz_assert.h>
|
|
|
|
/**
|
|
* \brief Calculates the distance between two buffers using the Myers algorithm
|
|
*
|
|
* Calculates the distance between two buffers using the Eugene W. Myers' O(ND) diff algorithm.
|
|
* - distance: is the minimum number of edits needed to transform A into B
|
|
* - similarity: is a number that defines how similar/identical the 2 buffers are.
|
|
* */
|
|
RZ_API bool rz_diff_myers_distance(RZ_NONNULL const ut8 *a, ut32 la, RZ_NONNULL const ut8 *b, ut32 lb, RZ_NULLABLE ut32 *distance, RZ_NULLABLE double *similarity) {
|
|
rz_return_val_if_fail(a && b, false);
|
|
|
|
const ut32 length = la + lb;
|
|
const ut8 *ea = a + la, *eb = b + lb;
|
|
|
|
for (; a < ea && b < eb && *a == *b; a++, b++) {
|
|
}
|
|
for (; a < ea && b < eb && ea[-1] == eb[-1]; ea--, eb--) {
|
|
}
|
|
la = ea - a;
|
|
lb = eb - b;
|
|
ut32 *v0, *v;
|
|
st64 m = (st64)la + lb, di = 0, low, high, i, x, y;
|
|
if (m + 2 > SIZE_MAX / sizeof(st64) || !(v0 = malloc((m + 2) * sizeof(ut32)))) {
|
|
return false;
|
|
}
|
|
v = v0 + lb;
|
|
v[1] = 0;
|
|
for (di = 0; di <= m; di++) {
|
|
low = -di + 2 * RZ_MAX(0, di - (st64)lb);
|
|
high = di - 2 * RZ_MAX(0, di - (st64)la);
|
|
for (i = low; i <= high; i += 2) {
|
|
x = i == -di || (i != di && v[i - 1] < v[i + 1]) ? v[i + 1] : v[i - 1] + 1;
|
|
y = x - i;
|
|
while (x < la && y < lb && a[x] == b[y]) {
|
|
x++;
|
|
y++;
|
|
}
|
|
v[i] = x;
|
|
if (x == la && y == lb) {
|
|
goto out;
|
|
}
|
|
}
|
|
}
|
|
|
|
out:
|
|
free(v0);
|
|
if (distance) {
|
|
*distance = di;
|
|
}
|
|
if (similarity) {
|
|
*similarity = length ? 1.0 - (double)di / length : 1.0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* \brief Calculates the distance between two buffers using the Levenshtein algorithm
|
|
*
|
|
* Calculates the distance between two buffers using the Levenshtein distance algorithm.
|
|
* - distance: is the minimum number of edits needed to transform A into B
|
|
* - similarity: is a number that defines how similar/identical the 2 buffers are.
|
|
* */
|
|
RZ_API bool rz_diff_levenshtein_distance(RZ_NONNULL const ut8 *a, ut32 la, RZ_NONNULL const ut8 *b, ut32 lb, RZ_NULLABLE ut32 *distance, RZ_NULLABLE double *similarity) {
|
|
rz_return_val_if_fail(a && b, false);
|
|
|
|
const ut32 length = RZ_MAX(la, lb);
|
|
const ut8 *ea = a + la, *eb = b + lb, *t;
|
|
ut32 *d, i, j;
|
|
|
|
for (; a < ea && b < eb && *a == *b; a++, b++) {
|
|
}
|
|
for (; a < ea && b < eb && ea[-1] == eb[-1]; ea--, eb--) {
|
|
}
|
|
la = ea - a;
|
|
lb = eb - b;
|
|
if (la < lb) {
|
|
i = la;
|
|
la = lb;
|
|
lb = i;
|
|
t = a;
|
|
a = b;
|
|
b = t;
|
|
}
|
|
|
|
if (sizeof(ut32) > SIZE_MAX / (lb + 1) || !(d = malloc((lb + 1) * sizeof(ut32)))) {
|
|
return false;
|
|
}
|
|
for (i = 0; i <= lb; i++) {
|
|
d[i] = i;
|
|
}
|
|
for (i = 0; i < la; i++) {
|
|
ut32 ul = d[0];
|
|
d[0] = i + 1;
|
|
for (j = 0; j < lb; j++) {
|
|
ut32 u = d[j + 1];
|
|
d[j + 1] = a[i] == b[j] ? ul : RZ_MIN(ul, RZ_MIN(d[j], u)) + 1;
|
|
ul = u;
|
|
}
|
|
}
|
|
|
|
if (distance) {
|
|
*distance = d[lb];
|
|
}
|
|
if (similarity) {
|
|
*similarity = length ? 1.0 - (double)d[lb] / length : 1.0;
|
|
}
|
|
free(d);
|
|
return true;
|
|
}
|