diff --git a/sefht.geany b/sefht.geany index 4533e6534a764063fb4ac199f60c943bd6bf5522..534fbaf823b3c8f9189cf91c8d9b0af24c87df98 100644 --- a/sefht.geany +++ b/sefht.geany @@ -28,34 +28,34 @@ long_line_behaviour=1 long_line_column=72 [files] -current_page=9 +current_page=22 FILE_NAME_0=607;Sh;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fconfigure.ac;0;8 FILE_NAME_1=395;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2FMakefile.am;0;8 FILE_NAME_2=847;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fmain.c;0;8 FILE_NAME_3=1067;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fcms.c;0;8 FILE_NAME_4=1148;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fcms.h;0;8 -FILE_NAME_5=4565;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fdata.c;0;8 +FILE_NAME_5=3598;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fdata.c;0;8 FILE_NAME_6=1099;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fdata.h;0;8 -FILE_NAME_7=1546;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Ffragment.c;0;8 +FILE_NAME_7=2130;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Ffragment.c;0;8 FILE_NAME_8=876;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Ffragment.h;0;8 -FILE_NAME_9=0;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Ftext.c;0;4 -FILE_NAME_10=0;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Ftext.h;0;4 -FILE_NAME_11=2888;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fvalidator.c;0;8 +FILE_NAME_9=2795;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Ftext.c;0;8 +FILE_NAME_10=1213;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Ftext.h;0;8 +FILE_NAME_11=3294;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fvalidator.c;0;8 FILE_NAME_12=900;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fvalidator.h;0;8 FILE_NAME_13=994;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Ferror.h;0;4 FILE_NAME_14=881;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flog.h;0;4 FILE_NAME_15=869;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fmacro.h;0;8 FILE_NAME_16=847;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fsefht.h;0;8 FILE_NAME_17=1025;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2FMakefile.am;0;8 -FILE_NAME_18=1253;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_cms.c;0;8 +FILE_NAME_18=1113;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_cms.c;0;8 FILE_NAME_19=3059;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_data.c;0;8 -FILE_NAME_20=2908;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_fragment.c;0;8 -FILE_NAME_21=0;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_text.c;0;4 -FILE_NAME_22=3404;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator.c;0;8 +FILE_NAME_20=2736;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_fragment.c;0;8 +FILE_NAME_21=2121;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_text.c;0;8 +FILE_NAME_22=4550;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator.c;0;8 FILE_NAME_23=55;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftodo.txt;0;8 [VTE] -last_dir=/home/jonathan/Dokumente/projekte/prgm/internet/web/SeFHT/src +last_dir=/home/jonathan/Dokumente/projekte/prgm/internet/web/SeFHT/tests [prjorg] source_patterns=*.c;*.C;*.cpp;*.cxx;*.c++;*.cc;*.m; diff --git a/src/Makefile.am b/src/Makefile.am index 7f7197403893fbcd33ec100d8efb1c5ab3612f47..f5ffd22d030a8b461802c1585dad5f4ad73f8efe 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,3 +15,5 @@ sefht_fcgi_SOURCES += data.c data.h sefht_fcgi_SOURCES += fragment.c fragment.h sefht_fcgi_SOURCES += text.c text.h sefht_fcgi_SOURCES += validator.c validator.h + +sefht_fcgi_LDADD = -lm diff --git a/src/text.c b/src/text.c index 29b22e929edd83dcbac1aca9a1081b9576079e07..d482fef1e2468d6bf2880c88ebfd985c23af16fe 100644 --- a/src/text.c +++ b/src/text.c @@ -22,8 +22,14 @@ */ +#include <errno.h> +#include <math.h> +#include <stdbool.h> +#include <stdint.h> #include <stdlib.h> +#include <string.h> +#include "macro.h" #include "error.h" #include "log.h" @@ -49,8 +55,8 @@ SH_Text_new (struct SH_Error * error) } text->length = 0; - text->size = 1; - text->text = malloc (1); + text->size = ALLOC_SIZE; + text->text = malloc (ALLOC_SIZE * sizeof (char)); text->text[0] = 0; if (error != NULL) @@ -75,3 +81,109 @@ SH_Text_free (struct SH_Text * text, struct SH_Error * error) return; } + +bool +SH_Text_enlarge (struct SH_Text * text, size_t size, + struct SH_Error * error) +{ + size_t new_size; + + if (size <= text->size) + { + if (error != NULL) + { + error->type = SUCCESS; + } + return TRUE; + } + + if (ALLOC_MANNER == LINEAR) + { + /* if both operands were integers, + * this operation would fail + * as the division will behave like + * calling floor in the first place. */ + if (ceilf (size / (float) ALLOC_SIZE) >= + (SIZE_MAX / (float) ALLOC_SIZE)) + { + ERROR1 ("Maximum length of text reached.\n"); + + if (error != NULL) + { + error->type = DOMAIN_ERROR; + } + + return FALSE; + } + + new_size = ceilf (size / (float) ALLOC_SIZE) * ALLOC_SIZE; + } + else if (ALLOC_MANNER == LOGARITHMIC) + { + if ((ceilf (logf (size) / logf (ALLOC_SIZE))) >= + (logf (SIZE_MAX) / logf (ALLOC_SIZE))) + { + ERROR1 ("Maximum length of text reached.\n"); + + if (error != NULL) + { + error->type = DOMAIN_ERROR; + } + + return FALSE; + } + + new_size = powf (ALLOC_SIZE, + ceilf (logf (size) / logf (ALLOC_SIZE))); + } + else + { + /* this isn't intended to be ever reached. */ + new_size = size; + } + + text->text = realloc (text->text, new_size * sizeof (char)); + + if (errno == ENOMEM) + { + ERROR1 ("Memory allocation for text data failed.\n"); + + if (error != NULL) + { + error->type = ALLOCATION_FAILED; + } + + return FALSE; + } + + text->size = new_size; + + if (error != NULL) + { + error->type = SUCCESS; + } + + return TRUE; +}; + +bool +SH_Text_append_string (struct SH_Text * text, char * string, + struct SH_Error * error) +{ + unsigned int length; + + length = strlen (string); + + if (!SH_Text_enlarge (text, text->length + length + 1, error)) + { + return FALSE; + } + + text->text = strcat (text->text, string); + + /* this is save as text->size is always at least one greater + * and SH_Text_enlarge hasn't failed. */ + text->length += length; + + return TRUE; +} diff --git a/src/text.h b/src/text.h index 91b987da48f57f0078d1246e4ac54aafce16dc15..d9b23365d084c7f495938abca31aa4670bf7f450 100644 --- a/src/text.h +++ b/src/text.h @@ -25,18 +25,32 @@ #ifndef _TEXT_H #define _TEXT_H +#include <stdbool.h> + #include "error.h" +enum { + LINEAR, + LOGARITHMIC +}; + +#define ALLOC_SIZE 64 +#define ALLOC_MANNER LINEAR + struct SH_Text { - unsigned int length; - unsigned int size; + size_t length; + size_t size; char * text; }; struct SH_Text * SH_Text_new (struct SH_Error * error); void SH_Text_free (struct SH_Text * text, struct SH_Error * error); +bool SH_Text_enlarge (struct SH_Text * text, size_t size, + struct SH_Error * error); +bool SH_Text_append_string (struct SH_Text * text, char * string, + struct SH_Error * error); #endif /* _TEXT_H */ diff --git a/tests/test_text.c b/tests/test_text.c index a35a0f22aa564e0b29d19dbb67a5230835c8e2ae..c1ab5dc935dda24570d1c643a30bda2c3872a116 100644 --- a/tests/test_text.c +++ b/tests/test_text.c @@ -23,9 +23,13 @@ #include <check.h> +#include <limits.h> +#include <stdbool.h> #include <stdlib.h> +#include "macro.h" #include "error.h" + #include "text.h" @@ -37,6 +41,8 @@ START_TEST(test_text) text = SH_Text_new (NULL); ck_assert_int_ne ((long int) text, (long int) NULL); + ck_assert_int_ge (text->size, ALLOC_SIZE); + SH_Text_free (text, NULL); error.type = UNDEFINED; @@ -44,12 +50,114 @@ START_TEST(test_text) ck_assert_int_ne ((long int) text, (long int) NULL); ck_assert_int_eq (error.type, SUCCESS); + ck_assert_int_ge (text->size, ALLOC_SIZE); + error.type = UNDEFINED; SH_Text_free (text, &error); ck_assert_int_eq (error.type, SUCCESS); } END_TEST +START_TEST(test_text_enlarge) +{ + struct SH_Error error; + struct SH_Text * text; + bool result; + unsigned int size1; + unsigned int size2; + unsigned int size2_; + unsigned int size3; + + if (ALLOC_MANNER == LINEAR) + { + size1 = ALLOC_SIZE; + size2 = ALLOC_SIZE + 1; + size2_ = 2 * ALLOC_SIZE; + if (UINT_MAX % ALLOC_SIZE == 0) + { + size3 = ((UINT_MAX / ALLOC_SIZE) - 1) * ALLOC_SIZE; + } + else + { + size3 = (UINT_MAX / ALLOC_SIZE) * ALLOC_SIZE; + } + } + else if (ALLOC_MANNER == LOGARITHMIC) + { + size1 = ALLOC_SIZE; + size2 = ALLOC_SIZE + 1; + size2_ = pow (ALLOC_SIZE, 2); + size3 = pow (ALLOC_SIZE, + (log (UINT_MAX) / log(ALLOC_SIZE))); + } + else + { + ck_abort_msg ("ALLOC_MANNER undefined"); + } + + text = SH_Text_new (NULL); + + /* size == current size */ + result = SH_Text_enlarge (text, size1, NULL); + ck_assert_int_eq (result, TRUE); + + ck_assert_int_eq (text->size, size1); + + /* size > current size */ + result = SH_Text_enlarge (text, size2, NULL); + ck_assert_int_eq (result, TRUE); + + ck_assert_int_eq (text->size, size2_); + + /* size < current size */ + result = SH_Text_enlarge (text, size1, NULL); + ck_assert_int_eq (result, TRUE); + + ck_assert_int_eq (text->size, size2_); + + /* size throw overflow */ + result = SH_Text_enlarge (text, size3, NULL); + ck_assert_int_eq (result, FALSE); + + SH_Text_free (text, NULL); + + + text = SH_Text_new (NULL); + + /* size == current size */ + error.type = UNDEFINED; + result = SH_Text_enlarge (text, size1, &error); + ck_assert_int_eq (result, TRUE); + ck_assert_int_eq (error.type, SUCCESS); + + ck_assert_int_eq (text->size, size1); + + /* size > current size */ + error.type = UNDEFINED; + result = SH_Text_enlarge (text, size2, NULL); + ck_assert_int_eq (result, TRUE); + ck_assert_int_eq (error.type, SUCCESS); + + ck_assert_int_eq (text->size, size2_); + + /* size < current size */ + error.type = UNDEFINED; + result = SH_Text_enlarge (text, size1, &error); + ck_assert_int_eq (result, TRUE); + ck_assert_int_eq (error.type, SUCCESS); + + ck_assert_int_eq (text->size, size2_); + + /* size throw overflow */ + error.type = UNDEFINED; + result = SH_Text_enlarge (text, size3, &error); + ck_assert_int_eq (result, FALSE); + ck_assert_int_eq (error.type, DOMAIN_ERROR); + + SH_Text_free (text, NULL); +} +END_TEST + Suite * text_suite (void) { Suite *s; @@ -61,6 +169,7 @@ Suite * text_suite (void) tc_core = tcase_create ("Core"); tcase_add_test (tc_core, test_text); + tcase_add_test (tc_core, test_text_enlarge); suite_add_tcase (s, tc_core); return s; diff --git a/tests/test_validator.c b/tests/test_validator.c index 2e909d2fd5eb54eae10e067d3422ba934a1048b8..f8ad1d3a63113872c01f4536dc3477aa71464024 100644 --- a/tests/test_validator.c +++ b/tests/test_validator.c @@ -123,6 +123,8 @@ START_TEST(test_validator_tag) SH_Validator_register_tag (validator, tagN, NULL); } + free (tagN); + tag = SH_Validator_register_tag (validator, tag2, NULL); ck_assert_int_eq (tag, TAG_ERR); @@ -145,6 +147,23 @@ START_TEST(test_validator_tag) tag_return = SH_Validator_get_tag (validator, tag3); ck_assert_int_eq (tag_return, TAG_ERR); + /* also free garbage created for overflow test */ + validator->tag_n = UINT_MAX; + + /* check tag */ + check = SH_Validator_check_tag (validator, tag1); + ck_assert_int_eq (check, TRUE); + + check = SH_Validator_check_tag (validator, tag2); + ck_assert_int_eq (check, FALSE); + + check = SH_Validator_check_tag (validator, tag3); + ck_assert_int_eq (check, FALSE); + + SH_Validator_free (validator, NULL); + + validator = SH_Validator_new (NULL); + /* success with error */ validator->last_tag = 1; @@ -182,6 +201,8 @@ START_TEST(test_validator_tag) SH_Validator_register_tag (validator, tagN, NULL); } + free (tagN); + error.type = UNDEFINED; tag = SH_Validator_register_tag (validator, tag5, &error); ck_assert_int_eq (tag, TAG_ERR); @@ -210,15 +231,6 @@ START_TEST(test_validator_tag) /* check tag */ - check = SH_Validator_check_tag (validator, tag1); - ck_assert_int_eq (check, TRUE); - - check = SH_Validator_check_tag (validator, tag2); - ck_assert_int_eq (check, FALSE); - - check = SH_Validator_check_tag (validator, tag3); - ck_assert_int_eq (check, FALSE); - check = SH_Validator_check_tag (validator, tag4); ck_assert_int_eq (check, TRUE); @@ -228,6 +240,8 @@ START_TEST(test_validator_tag) check = SH_Validator_check_tag (validator, tag6); ck_assert_int_eq (check, FALSE); + /* also free garbage created for overflow test */ + validator->tag_n = UINT_MAX; SH_Validator_free (validator, NULL); }