diff options
-rw-r--r-- | lib/Kconfig | 3 | ||||
-rw-r--r-- | lib/string.c | 129 |
2 files changed, 132 insertions, 0 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index 6762529ad9e4..40b114a11d7c 100644 --- a/lib/Kconfig +++ b/lib/Kconfig | |||
@@ -575,4 +575,7 @@ config PARMAN | |||
575 | config PRIME_NUMBERS | 575 | config PRIME_NUMBERS |
576 | tristate | 576 | tristate |
577 | 577 | ||
578 | config STRING_SELFTEST | ||
579 | bool "Test string functions" | ||
580 | |||
578 | endmenu | 581 | endmenu |
diff --git a/lib/string.c b/lib/string.c index 198148bb61fd..abf6499e3915 100644 --- a/lib/string.c +++ b/lib/string.c | |||
@@ -1051,3 +1051,132 @@ void fortify_panic(const char *name) | |||
1051 | BUG(); | 1051 | BUG(); |
1052 | } | 1052 | } |
1053 | EXPORT_SYMBOL(fortify_panic); | 1053 | EXPORT_SYMBOL(fortify_panic); |
1054 | |||
1055 | #ifdef CONFIG_STRING_SELFTEST | ||
1056 | #include <linux/slab.h> | ||
1057 | #include <linux/module.h> | ||
1058 | |||
1059 | static __init int memset16_selftest(void) | ||
1060 | { | ||
1061 | unsigned i, j, k; | ||
1062 | u16 v, *p = kmalloc(256 * 2 * 2, GFP_KERNEL); | ||
1063 | |||
1064 | for (i = 0; i < 256; i++) { | ||
1065 | for (j = 0; j < 256; j++) { | ||
1066 | memset(p, 0xa1, 256 * 2 * sizeof(v)); | ||
1067 | memset16(p + i, 0xb1b2, j); | ||
1068 | for (k = 0; k < 512; k++) { | ||
1069 | v = p[k]; | ||
1070 | if (k < i) { | ||
1071 | if (v != 0xa1a1) | ||
1072 | goto fail; | ||
1073 | } else if (k < i + j) { | ||
1074 | if (v != 0xb1b2) | ||
1075 | goto fail; | ||
1076 | } else { | ||
1077 | if (v != 0xa1a1) | ||
1078 | goto fail; | ||
1079 | } | ||
1080 | } | ||
1081 | } | ||
1082 | } | ||
1083 | |||
1084 | fail: | ||
1085 | kfree(p); | ||
1086 | if (i < 256) | ||
1087 | return (i << 24) | (j << 16) | k; | ||
1088 | return 0; | ||
1089 | } | ||
1090 | |||
1091 | static __init int memset32_selftest(void) | ||
1092 | { | ||
1093 | unsigned i, j, k; | ||
1094 | u32 v, *p = kmalloc(256 * 2 * 4, GFP_KERNEL); | ||
1095 | |||
1096 | for (i = 0; i < 256; i++) { | ||
1097 | for (j = 0; j < 256; j++) { | ||
1098 | memset(p, 0xa1, 256 * 2 * sizeof(v)); | ||
1099 | memset32(p + i, 0xb1b2b3b4, j); | ||
1100 | for (k = 0; k < 512; k++) { | ||
1101 | v = p[k]; | ||
1102 | if (k < i) { | ||
1103 | if (v != 0xa1a1a1a1) | ||
1104 | goto fail; | ||
1105 | } else if (k < i + j) { | ||
1106 | if (v != 0xb1b2b3b4) | ||
1107 | goto fail; | ||
1108 | } else { | ||
1109 | if (v != 0xa1a1a1a1) | ||
1110 | goto fail; | ||
1111 | } | ||
1112 | } | ||
1113 | } | ||
1114 | } | ||
1115 | |||
1116 | fail: | ||
1117 | kfree(p); | ||
1118 | if (i < 256) | ||
1119 | return (i << 24) | (j << 16) | k; | ||
1120 | return 0; | ||
1121 | } | ||
1122 | |||
1123 | static __init int memset64_selftest(void) | ||
1124 | { | ||
1125 | unsigned i, j, k; | ||
1126 | u64 v, *p = kmalloc(256 * 2 * 8, GFP_KERNEL); | ||
1127 | |||
1128 | for (i = 0; i < 256; i++) { | ||
1129 | for (j = 0; j < 256; j++) { | ||
1130 | memset(p, 0xa1, 256 * 2 * sizeof(v)); | ||
1131 | memset64(p + i, 0xb1b2b3b4b5b6b7b8ULL, j); | ||
1132 | for (k = 0; k < 512; k++) { | ||
1133 | v = p[k]; | ||
1134 | if (k < i) { | ||
1135 | if (v != 0xa1a1a1a1a1a1a1a1ULL) | ||
1136 | goto fail; | ||
1137 | } else if (k < i + j) { | ||
1138 | if (v != 0xb1b2b3b4b5b6b7b8ULL) | ||
1139 | goto fail; | ||
1140 | } else { | ||
1141 | if (v != 0xa1a1a1a1a1a1a1a1ULL) | ||
1142 | goto fail; | ||
1143 | } | ||
1144 | } | ||
1145 | } | ||
1146 | } | ||
1147 | |||
1148 | fail: | ||
1149 | kfree(p); | ||
1150 | if (i < 256) | ||
1151 | return (i << 24) | (j << 16) | k; | ||
1152 | return 0; | ||
1153 | } | ||
1154 | |||
1155 | static __init int string_selftest_init(void) | ||
1156 | { | ||
1157 | int test, subtest; | ||
1158 | |||
1159 | test = 1; | ||
1160 | subtest = memset16_selftest(); | ||
1161 | if (subtest) | ||
1162 | goto fail; | ||
1163 | |||
1164 | test = 2; | ||
1165 | subtest = memset32_selftest(); | ||
1166 | if (subtest) | ||
1167 | goto fail; | ||
1168 | |||
1169 | test = 3; | ||
1170 | subtest = memset64_selftest(); | ||
1171 | if (subtest) | ||
1172 | goto fail; | ||
1173 | |||
1174 | pr_info("String selftests succeeded\n"); | ||
1175 | return 0; | ||
1176 | fail: | ||
1177 | pr_crit("String selftest failure %d.%08x\n", test, subtest); | ||
1178 | return 0; | ||
1179 | } | ||
1180 | |||
1181 | module_init(string_selftest_init); | ||
1182 | #endif /* CONFIG_STRING_SELFTEST */ | ||