基于C语言crypt函数结合文件的认证(段错误问题)
Hey there, let's break down why you might be hitting that segmentation fault in your password verification flow, and walk through the most likely fixes:
Segmentation faults almost always stem from invalid memory access—so let's target the parts of your code that handle log_password, encryption, and file reads first.
1. Uninitialized/Under-sized Buffers for log_password
If log_password is a pointer without allocated memory, or a static array that's too small for user input, writing to it will corrupt adjacent memory and trigger a fault.
- Fix:
- Use a sufficiently sized static array (e.g.,
char log_password[128];) instead of an uninitialized pointer. - Avoid unsafe functions like
gets()—usefgets()to read input and enforce buffer limits, then strip the trailing newline:fgets(log_password, sizeof(log_password), stdin); log_password[strcspn(log_password, "\n")] = '\0';
- Use a sufficiently sized static array (e.g.,
2. Misusing the crypt() Function
crypt() requires a valid salt parameter to generate a matching hash. If you're passing an uninitialized pointer, NULL, or an incorrectly extracted salt from your stored passwords, it will crash.
- How it works: Stored hashes from
crypt()follow a format like$id$salt$encrypted(e.g., MD5 hashes start with$1$). You need to pass the entire prefix (including the salt) as the second argument tocrypt()—it automatically parses the salt from this string. - Fix:
When reading a stored hash from your file, pass that full hash string directly as the salt tocrypt():
Also, always check ifchar stored_hash[256]; // (read stored_hash from file first) char *hashed_input = crypt(log_password, stored_hash);crypt()returns NULL (this means it failed, which could also cause crashes if you try to use the result).
3. Unchecked File Operations
If your code doesn't verify that the password file opens successfully in case 2, you'll end up reading from a NULL pointer when trying to access stored hashes.
- Fix:
Add a check right after opening the file:
Also, ensure your buffer for storing hashes from the file is large enough and initialized before reading into it.FILE *fp = fopen("passwords.txt", "r"); if (fp == NULL) { perror("Failed to open password file"); break; }
4. Example Corrected Case 2 Snippet
Here's a quick example of how your verification flow could look with these fixes applied:
case 2: { char log_password[128]; char stored_hash[256]; char *hashed_input; FILE *fp = fopen("passwords.txt", "r"); // Check file open success if (fp == NULL) { perror("Could not open password file"); break; } printf("Enter password to verify: "); // Safe input reading if (fgets(log_password, sizeof(log_password), stdin) == NULL) { perror("Failed to read input"); fclose(fp); break; } log_password[strcspn(log_password, "\n")] = '\0'; // Read and check each stored hash while (fgets(stored_hash, sizeof(stored_hash), fp) != NULL) { // Remove newline from stored hash stored_hash[strcspn(stored_hash, "\n")] = '\0'; // Generate hash with correct salt hashed_input = crypt(log_password, stored_hash); if (hashed_input == NULL) { perror("Crypt function failed"); fclose(fp); break; } // Compare hashes if (strcmp(hashed_input, stored_hash) == 0) { printf("Password verified!\n"); fclose(fp); return 0; } } printf("Invalid password.\n"); fclose(fp); break; }
- Verify all buffers (for input and stored hashes) are properly initialized and sized.
- Double-check that every file operation (open, read) has error handling.
- Ensure you're not accessing pointers that could be NULL (like
crypt()'s return value).
内容的提问来源于stack exchange,提问作者JHk1821

