/* constructor */ PyObject * sr_py_distances_part_new(PyTypeObject *object, PyObject *args, PyObject *kwds) { int m, n, m_begin, n_begin; unsigned long long len; enum sr_distance_type dist_type; unsigned long long checksum; PyObject *dist_list; if (!PyArg_ParseTuple(args, "iiiiKiKO", &m, &n, &m_begin, &n_begin, &len, &dist_type, &checksum, &dist_list)) return NULL; struct sr_distances_part *part = sr_distances_part_new(m, n, dist_type, m_begin, n_begin, (size_t)len); part->checksum = (uint32_t)checksum; if (PyList_Check(dist_list)) { part->distances = sr_malloc_array(sizeof(float), part->len); int i; for (i = 0; i < PyList_Size(dist_list); i++) { PyObject *item = PyList_GetItem(dist_list, i); if (!item) goto error; double d = PyFloat_AsDouble(item); if (PyErr_Occurred()) goto error; part->distances[i] = (float)d; } } else if (dist_list != Py_None) { PyErr_SetString(PyExc_TypeError, "distances must be list of floats or None"); goto error; } struct sr_py_distances_part *py_part = PyObject_New(struct sr_py_distances_part, &sr_py_distances_part_type); py_part->distances_part = part; return (PyObject *)py_part; error: sr_distances_part_free(part, false); return NULL; }
struct sr_distances * sr_distances_new(int m, int n) { struct sr_distances *distances = sr_malloc(sizeof(struct sr_distances)); /* The number of rows has to be smaller than columns. */ if (m >= n) m = n - 1; assert(m > 0 && n > 1 && m < n); distances->m = m; distances->n = n; distances->distances = sr_malloc_array( get_distance_position(distances, m - 1, n - 1) + 1, sizeof(*distances->distances) ); return distances; }
float distance_levenshtein(struct sr_thread *thread1, struct sr_thread *thread2, bool transposition) { assert(thread1->type == thread2->type); int frame_count1 = sr_thread_frame_count(thread1); int frame_count2 = sr_thread_frame_count(thread2); int max_frame_count = frame_count2; if (max_frame_count < frame_count1) max_frame_count = frame_count1; /* Avoid division by zero in case we get two empty threads */ if (max_frame_count == 0) return 0.0; int m = frame_count1 + 1; int n = frame_count2 + 1; // store only two last rows and columns instead of whole 2D array SR_ASSERT(n <= SIZE_MAX - 1); SR_ASSERT(m <= SIZE_MAX - (n + 1)); int *dist = sr_malloc_array(sizeof(int), m + n + 1); int *dist1 = sr_malloc_array(sizeof(int), m + n + 1); // first row and column having distance equal to their position for (int i = m; i > 0; --i) dist[m - i] = i; for (int i = 0; i <= n; ++i) dist[m + i] = i; struct sr_frame *curr_frame2 = sr_thread_frames(thread2); struct sr_frame *prev_frame = NULL; struct sr_frame *prev_frame2 = NULL; for (int j = 1; curr_frame2; ++j) { struct sr_frame *curr_frame = sr_thread_frames(thread1); for (int i = 1; curr_frame; ++i) { int l = m + j - i; int dist2 = dist1[l]; dist1[l] = dist[l]; int cost; /*similar characters have distance equal to the previous one diagonally, "??" functions aren't taken as similar */ if (0 == sr_frame_cmp_distance(curr_frame, curr_frame2)) cost = 0; else { // different ones takes the lowest value of all // previous distances cost = 1; dist[l] += 1; if (dist[l] > dist[l - 1] + 1) dist[l] = dist[l - 1] + 1; if (dist[l] > dist[l + 1] + 1) dist[l] = dist[l + 1] + 1; } /*checking for transposition of two characters in both ways taking into account that "??" functions are not similar*/ if (transposition && (i >= 2 && j >= 2 && dist[l] > dist2 + cost && 0 == sr_frame_cmp_distance(curr_frame, prev_frame2) && 0 == sr_frame_cmp_distance(prev_frame, curr_frame2))) { dist[l] = dist2 + cost; } prev_frame = curr_frame; curr_frame = sr_frame_next(curr_frame); } prev_frame2 = curr_frame2; curr_frame2 = sr_frame_next(curr_frame2); } int result = dist[n]; free(dist); free(dist1); return (float)result / max_frame_count; }
struct sr_koops_stacktrace * sr_koops_stacktrace_from_json(struct sr_json_value *root, char **error_message) { if (!JSON_CHECK_TYPE(root, SR_JSON_OBJECT, "stacktrace")) return NULL; struct sr_koops_stacktrace *result = sr_koops_stacktrace_new(); /* Kernel version. */ if (!JSON_READ_STRING(root, "version", &result->version)) goto fail; /* Raw oops text. */ if (!JSON_READ_STRING(root, "raw_oops", &result->raw_oops)) goto fail; /* Kernel taint flags. */ struct sr_json_value *taint_flags = json_element(root, "taint_flags"); if (taint_flags) { if (!JSON_CHECK_TYPE(taint_flags, SR_JSON_ARRAY, "taint_flags")) goto fail; struct sr_json_value *flag_json; FOR_JSON_ARRAY(taint_flags, flag_json) { if (!JSON_CHECK_TYPE(flag_json, SR_JSON_STRING, "taint flag")) goto fail; for (struct sr_taint_flag *f = sr_flags; f->name; f++) { if (0 == strcmp(f->name, flag_json->u.string.ptr)) { *(bool *)((void *)result + f->member_offset) = true; break; } } /* XXX should we do something if nothing is set? */ } } /* Modules. */ struct sr_json_value *modules = json_element(root, "modules"); if (modules) { if (!JSON_CHECK_TYPE(modules, SR_JSON_ARRAY, "modules")) goto fail; unsigned i = 0; size_t allocated = 128; result->modules = sr_malloc_array(allocated, sizeof(char*)); struct sr_json_value *mod_json; FOR_JSON_ARRAY(modules, mod_json) { if (!JSON_CHECK_TYPE(mod_json, SR_JSON_STRING, "module")) goto fail; /* need to keep the last element for NULL terminator */ if (i+1 == allocated) { allocated *= 2; result->modules = sr_realloc(result->modules, allocated); } result->modules[i] = sr_strdup(mod_json->u.string.ptr); i++; } result->modules[i] = NULL; } /* Frames. */ struct sr_json_value *frames = json_element(root, "frames"); if (frames) { if (!JSON_CHECK_TYPE(frames, SR_JSON_ARRAY, "frames")) goto fail; struct sr_json_value *frame_json; FOR_JSON_ARRAY(frames, frame_json) { struct sr_koops_frame *frame = sr_koops_frame_from_json(frame_json, error_message); if (!frame) goto fail; result->frames = sr_koops_frame_append(result->frames, frame); } } return result; fail: sr_koops_stacktrace_free(result); return NULL; }