Skip to content

Commit 4e9a926

Browse files
committed
fix: resolve integer overflow risks and improve CLI validation
- Fix integer overflow in verify.cuh: use size_t for element counts - Fix integer overflow in tensor_core_sgemm.cuh: use size_t for grid calc - Replace atoi() with safeStrToInt() for robust CLI parsing - Add .clang-tidy for static analysis configuration - Remove duplicate LICENSE file (keep LICENSE.md with third-party info)
1 parent 3a1643b commit 4e9a926

5 files changed

Lines changed: 111 additions & 41 deletions

File tree

.clang-tidy

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
# Clang-tidy configuration for SGEMM Optimization Project
3+
# Focuses on correctness and performance issues, avoids style nitpicks
4+
5+
Checks: >
6+
-*,
7+
bugprone-*,
8+
-bugprone-easily-swappable-parameters,
9+
concurrency-*,
10+
modernize-*,
11+
-modernize-use-trailing-return-type,
12+
-modernize-use-nodiscard,
13+
performance-*,
14+
readability-identifier-naming,
15+
-readability-function-cognitive-complexity,
16+
-readability-identifier-length,
17+
-readability-magic-numbers
18+
19+
WarningsAsErrors: ''
20+
21+
HeaderFilterRegex: '.*'
22+
23+
CheckOptions:
24+
- key: readability-identifier-naming.NamespaceCase
25+
value: lower_case
26+
- key: readability-identifier-naming.FunctionCase
27+
value: lower_case
28+
- key: readability-identifier-naming.VariableCase
29+
value: lower_case
30+
- key: readability-identifier-naming.ConstantCase
31+
value: UPPER_CASE
32+
- key: readability-identifier-naming.ConstantPrefix
33+
value: 'k'
34+
- key: readability-identifier-naming.ParameterCase
35+
value: lower_case
36+
- key: readability-identifier-naming.StructCase
37+
value: lower_case
38+
- key: readability-identifier-naming.ClassCase
39+
value: lower_case
40+
- key: readability-identifier-naming.EnumConstantCase
41+
value: lower_case
42+
- key: readability-identifier-naming.MemberCase
43+
value: lower_case
44+
- key: readability-identifier-naming.PrivateMemberSuffix
45+
value: '_'
46+
- key: performance-move-const-arg.CheckTriviallyCopyableMove
47+
value: '0'

LICENSE

Lines changed: 0 additions & 21 deletions
This file was deleted.

src/kernels/tensor_core_sgemm.cuh

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,15 +123,19 @@ inline void launch_tensor_core_sgemm(const float *A, const float *B, float *C, i
123123
return;
124124
}
125125

126-
DeviceMemory<half> d_A_fp16(M * K);
127-
DeviceMemory<half> d_B_fp16(K * N);
126+
size_t num_A = static_cast<size_t>(M) * K;
127+
size_t num_B = static_cast<size_t>(K) * N;
128+
DeviceMemory<half> d_A_fp16(num_A);
129+
DeviceMemory<half> d_B_fp16(num_B);
128130

129131
int blockSize = 256;
130-
int gridSizeA = (M * K + blockSize - 1) / blockSize;
131-
int gridSizeB = (K * N + blockSize - 1) / blockSize;
132+
int gridSizeA = static_cast<int>((num_A + blockSize - 1) / blockSize);
133+
int gridSizeB = static_cast<int>((num_B + blockSize - 1) / blockSize);
132134

133-
float_to_half_kernel<<<gridSizeA, blockSize, 0, stream>>>(A, d_A_fp16.get(), M * K);
134-
float_to_half_kernel<<<gridSizeB, blockSize, 0, stream>>>(B, d_B_fp16.get(), K * N);
135+
float_to_half_kernel<<<gridSizeA, blockSize, 0, stream>>>(A, d_A_fp16.get(),
136+
static_cast<int>(num_A));
137+
float_to_half_kernel<<<gridSizeB, blockSize, 0, stream>>>(B, d_B_fp16.get(),
138+
static_cast<int>(num_B));
135139
CUDA_CHECK(cudaGetLastError());
136140

137141
launch_tensor_core_sgemm_fp16_fast_path(d_A_fp16.get(), d_B_fp16.get(), C, M, K, N, stream);

src/main.cu

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
* GPU matrix multiplication optimization techniques.
77
*/
88

9+
#include <cerrno>
10+
#include <climits>
911
#include <cstdio>
1012
#include <cstdlib>
1113
#include <string>
@@ -32,6 +34,30 @@ const std::vector<std::tuple<int, int, int>> DEFAULT_CASES = {
3234
{256, 384, 640},
3335
{511, 513, 1025},
3436
};
37+
38+
// Safe string to int conversion with error handling
39+
bool safeStrToInt(const char *str, int *result, const char *argName) {
40+
if (str == nullptr || str[0] == '\0') {
41+
fprintf(stderr, "Error: %s requires a valid number\n", argName);
42+
return false;
43+
}
44+
45+
char *endptr;
46+
errno = 0;
47+
long val = strtol(str, &endptr, 10);
48+
49+
if (errno == ERANGE || val > INT_MAX || val < INT_MIN) {
50+
fprintf(stderr, "Error: %s value '%s' is out of range\n", argName, str);
51+
return false;
52+
}
53+
if (*endptr != '\0') {
54+
fprintf(stderr, "Error: Invalid %s value '%s' (not a valid integer)\n", argName, str);
55+
return false;
56+
}
57+
58+
*result = static_cast<int>(val);
59+
return true;
60+
}
3561
} // namespace
3662

3763
void naive_kernel(const float *A, const float *B, float *C, int M, int K, int N) {
@@ -168,7 +194,10 @@ int main(int argc, char **argv) {
168194
return 1;
169195
}
170196

171-
int size = atoi(argv[++i]);
197+
int size;
198+
if (!safeStrToInt(argv[++i], &size, "size")) {
199+
return 1;
200+
}
172201
if (size <= 0) {
173202
fprintf(stderr, "Error: Size must be positive\n");
174203
return 1;
@@ -184,9 +213,12 @@ int main(int argc, char **argv) {
184213
return 1;
185214
}
186215

187-
int M = atoi(argv[++i]);
188-
int K = atoi(argv[++i]);
189-
int N = atoi(argv[++i]);
216+
int M, K, N;
217+
if (!safeStrToInt(argv[++i], &M, "M dimension") ||
218+
!safeStrToInt(argv[++i], &K, "K dimension") ||
219+
!safeStrToInt(argv[++i], &N, "N dimension")) {
220+
return 1;
221+
}
190222
if (M <= 0 || K <= 0 || N <= 0) {
191223
fprintf(stderr, "Error: Dimensions must be positive\n");
192224
return 1;
@@ -207,7 +239,10 @@ int main(int argc, char **argv) {
207239
return 1;
208240
}
209241

210-
int warmup = atoi(argv[++i]);
242+
int warmup;
243+
if (!safeStrToInt(argv[++i], &warmup, "warmup")) {
244+
return 1;
245+
}
211246
if (warmup < 0) {
212247
fprintf(stderr, "Error: Warmup runs must be non-negative\n");
213248
return 1;
@@ -223,7 +258,10 @@ int main(int argc, char **argv) {
223258
return 1;
224259
}
225260

226-
int bench = atoi(argv[++i]);
261+
int bench;
262+
if (!safeStrToInt(argv[++i], &bench, "benchmark")) {
263+
return 1;
264+
}
227265
if (bench <= 0) {
228266
fprintf(stderr, "Error: Benchmark runs must be positive\n");
229267
return 1;

src/utils/verify.cuh

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ struct VerifyResult {
1818
float max_abs_error;
1919
float max_rel_error;
2020
int error_count;
21-
int total_elements;
21+
size_t total_elements;
2222

2323
void print(const char *kernel_name = "Kernel") const {
2424
printf(" %s Verification: %s\n", kernel_name, passed ? "PASSED" : "FAILED");
2525
printf(" Max Absolute Error: %.6e\n", max_abs_error);
2626
printf(" Max Relative Error: %.6e\n", max_rel_error);
2727
if (!passed) {
28-
printf(" Error Count: %d / %d (%.2f%%)\n", error_count, total_elements,
28+
printf(" Error Count: %d / %zu (%.2f%%)\n", error_count, total_elements,
2929
100.0f * error_count / total_elements);
3030
}
3131
}
@@ -112,12 +112,14 @@ class SGEMMVerifier {
112112
// Verify with device pointers (copies to host internally)
113113
VerifyResult verifyDevice(const float *d_test, const float *d_ref, int M, int N,
114114
VerifyTolerance tolerance = kStandardVerifyTolerance) {
115-
std::vector<float> h_test(M * N);
116-
std::vector<float> h_ref(M * N);
115+
size_t num_elements = static_cast<size_t>(M) * N;
116+
std::vector<float> h_test(num_elements);
117+
std::vector<float> h_ref(num_elements);
117118

119+
CUDA_CHECK(cudaMemcpy(h_test.data(), d_test, num_elements * sizeof(float),
120+
cudaMemcpyDeviceToHost));
118121
CUDA_CHECK(
119-
cudaMemcpy(h_test.data(), d_test, M * N * sizeof(float), cudaMemcpyDeviceToHost));
120-
CUDA_CHECK(cudaMemcpy(h_ref.data(), d_ref, M * N * sizeof(float), cudaMemcpyDeviceToHost));
122+
cudaMemcpy(h_ref.data(), d_ref, num_elements * sizeof(float), cudaMemcpyDeviceToHost));
121123

122124
return verify(h_test.data(), h_ref.data(), M, N, tolerance);
123125
}
@@ -143,9 +145,9 @@ inline VerifyResult compareMatrices(const float *h_test, const float *h_ref, int
143145
result.max_abs_error = 0.0f;
144146
result.max_rel_error = 0.0f;
145147
result.error_count = 0;
146-
result.total_elements = M * N;
148+
result.total_elements = static_cast<size_t>(M) * N;
147149

148-
for (int i = 0; i < M * N; ++i) {
150+
for (size_t i = 0; i < static_cast<size_t>(M) * N; ++i) {
149151
float ref_val = h_ref[i];
150152
float test_val = h_test[i];
151153

0 commit comments

Comments
 (0)