diff --git a/analyzers/polynomials/poly_calc/poly_calc.c b/analyzers/polynomials/poly_calc/poly_calc.c index e377580..583a97c 100644 --- a/analyzers/polynomials/poly_calc/poly_calc.c +++ b/analyzers/polynomials/poly_calc/poly_calc.c @@ -2,6 +2,27 @@ #include #include #include +#include + +// Безопасное умножение с проверкой переполнения +int safe_mul(int a, int b) { + if (a > 0) { + if (b > 0 && a > INT_MAX / b) return 0; // Переполнение + if (b < 0 && b < INT_MIN / a) return 0; // Переполнение + } else if (a < 0) { + if (b > 0 && a < INT_MIN / b) return 0; // Переполнение + if (b < 0 && a < INT_MAX / b) return 0; // Переполнение + } + return a * b; +} + +// Безопасное сложение с проверкой переполнения +int safe_add(int a, int b) { + if ((b > 0 && a > INT_MAX - b) || (b < 0 && a < INT_MIN - b)) { + return 0; // Переполнение + } + return a + b; +} // Возведение полинома в целую степень Polynomial deg_poly(Polynomial *p, int degree) { @@ -33,13 +54,26 @@ Polynomial mul_polynomials(Polynomial *p1, Polynomial *p2) { Term t1 = p1->terms[i]; Term t2 = p2->terms[j]; - // Результат перемножения двух слагаемых - Term res_t; - res_t.coefficient = t1.coefficient * t2.coefficient; - res_t.exponent = t1.exponent + t2.exponent; + // Безопасное умножение коэффициентов + int safe_coeff = safe_mul(t1.coefficient, t2.coefficient); + if (t1.coefficient != 0 && t2.coefficient != 0 && safe_coeff == 0) { + fprintf(stderr, "Multiplication overflow detected!\n"); + free_polynomial(&result); + exit(EXIT_FAILURE); + } + + // Безопасное сложение степеней + int safe_exp = safe_add(t1.exponent, t2.exponent); + if (safe_exp == 0 && (t1.exponent != 0 || t2.exponent != 0)) { + fprintf(stderr, "Exponent addition overflow detected!\n"); + free_polynomial(&result); + exit(EXIT_FAILURE); + } + + Term res_t; + res_t.coefficient = safe_coeff; + res_t.exponent = safe_exp; - // Прибавление полученного результата (слагаемого) - // к результирующему полиному add_term_and_poly(&result, res_t); } } @@ -49,12 +83,16 @@ Polynomial mul_polynomials(Polynomial *p1, Polynomial *p2) { Polynomial sub_polynomials(Polynomial *p1, Polynomial *p2) { for (int i = 0; i < p2->size; ++i) { + // Безопасное умножение на -1 + if (p2->terms[i].coefficient == INT_MIN) { + fprintf(stderr, "Overflow when negating coefficient!\n"); + exit(EXIT_FAILURE); + } p2->terms[i].coefficient *= -1; } return add_polynomials(p1, p2); } -// Cложение полиномов Polynomial add_polynomials(Polynomial *p1, Polynomial *p2) { Polynomial result; init_polynomial(&result); @@ -69,18 +107,23 @@ Polynomial add_polynomials(Polynomial *p1, Polynomial *p2) { return result; } -// Сложение одного слагаемого и полинома void add_term_and_poly(Polynomial *p, Term term) { Term* t = exist_incremental(p, term); - if (t) { - t->coefficient += term.coefficient; - } else { - add_term(p, term.coefficient, term.exponent); + if (t) { + // Безопасное сложение коэффициентов + int new_coeff = safe_add(t->coefficient, term.coefficient); + if (new_coeff == 0 && ((t->coefficient > 0 && term.coefficient > 0) || + (t->coefficient < 0 && term.coefficient < 0))) { + fprintf(stderr, "Coefficient addition overflow detected!\n"); + exit(EXIT_FAILURE); + } + t->coefficient = new_coeff; + } else { + add_term(p, term.coefficient, term.exponent); } } -// Например есть полином x+1 и терм (2,1)=2x, значит в полиноме есть -// incremental (увеличиваемое), т.е. есть к чему прибавить 2x +// Остальные функции остаются без изменений Term* exist_incremental(Polynomial *p, Term term) { for (int i = 0; i < p->size; ++i) { if (p->terms[i].exponent == term.exponent) { @@ -90,7 +133,6 @@ Term* exist_incremental(Polynomial *p, Term term) { return NULL; } -// Инициализация полинома void init_polynomial(Polynomial *p) { p->size = 0; p->capacity = 4; @@ -101,9 +143,7 @@ void init_polynomial(Polynomial *p) { } } -// Добавление слагаемого в полином void add_term(Polynomial *p, int coeff, int exp) { - // Проверяем, нужно ли расширить массив if (p->size >= p->capacity) { p->capacity *= 2; p->terms = (Term *)realloc(p->terms, p->capacity * sizeof(Term)); @@ -113,18 +153,15 @@ void add_term(Polynomial *p, int coeff, int exp) { } } - // Добавляем слагаемое p->terms[p->size].coefficient = coeff; p->terms[p->size].exponent = exp; p->size++; } -// Сортировка слагаемых в полиноме по убыванию степени void sort_polynomial(Polynomial *p) { for (int i = 0; i < p->size - 1; i++) { for (int j = 0; j < p->size - i - 1; j++) { if (p->terms[j].exponent < p->terms[j + 1].exponent) { - // Обмен слагаемых Term temp = p->terms[j]; p->terms[j] = p->terms[j + 1]; p->terms[j + 1] = temp; @@ -133,7 +170,6 @@ void sort_polynomial(Polynomial *p) { } } -// Освобождение памяти, занятой полиномом void free_polynomial(Polynomial *p) { free(p->terms); p->terms = NULL; @@ -141,7 +177,6 @@ void free_polynomial(Polynomial *p) { p->capacity = 0; } -// Печать полинома void print_polynomial(Polynomial *p, char letter) { if (p->size == 0) { printf("0\n"); @@ -151,26 +186,20 @@ void print_polynomial(Polynomial *p, char letter) { for (int i = 0; i < p->size; i++) { Term term = p->terms[i]; - if (term.coefficient == 0) { - continue; - } + if (term.coefficient == 0) continue; - // Печать знака (не печатаем '+' перед первым слагаемым) if (i != 0 || term.coefficient < 0) { printf("%c", term.coefficient > 0 ? '+' : '-'); } - // Печать коэффициента (если не 1/-1 или если степень 0) if (abs(term.coefficient) != 1 || term.exponent == 0) { printf("%d", abs(term.coefficient)); } else if (term.coefficient == -1 && term.exponent != 0) { - printf("-"); // Специальный случай для -x^n + printf("-"); } - // Печать переменной if (term.exponent > 0) { printf("%c", letter); - // Печать степени только если она больше 1 if (term.exponent > 1) { printf("^%d", term.exponent); } diff --git a/analyzers/polynomials/polynomials.l b/analyzers/polynomials/polynomials.l index 5622847..8d7d98a 100644 --- a/analyzers/polynomials/polynomials.l +++ b/analyzers/polynomials/polynomials.l @@ -6,6 +6,8 @@ extern FILE *yyin; char allowed_variable = 0; int current_line_number = 1; +const char* INT_MAX_STR = "2147483646"; + void yyerror(const char *s) { fprintf(stderr, "Error at line %i: %s\n", current_line_number, s); } @@ -17,6 +19,16 @@ void yyerror(const char *s) { ";" { return SEMICOLON; } "=" { return EQUAL; } [0-9]+ { + size_t len = strlen(yytext); + if (len > strlen(INT_MAX_STR)) { + yyerror("Number too large (max 2147483646)"); + exit(-1); + } else if (len == strlen(INT_MAX_STR)) { + if (strcmp(yytext, INT_MAX_STR) > 0) { + yyerror("Number too large (max 2147483646)"); + exit(-1); + } + } init_polynomial(&yylval.poly); add_term(&yylval.poly, atoi(yytext), 0); return NUMBER; diff --git a/poly.txt b/poly.txt index ec457d4..c3d195c 100644 --- a/poly.txt +++ b/poly.txt @@ -1,4 +1,6 @@ -A = (x+2)^2; +A = x+2; +A = A^2; +print A; A = A + A + 2; print A; @@ -10,4 +12,6 @@ A = (x-2)*(x^2+2*x+4); print A; +print 2147483646*2; + print 2+2*3; \ No newline at end of file