1

如何使用 C 的 SAL 注释编写此函数?我需要实现一些功能,但我不知道如何声明它们。我只需要 1 个函数作为模型,所以我可以实现其余的。

下面是我的主要 C 文件,其中包含我已经实现的所有句柄,我不需要修改它。

static void
PrintHelp()
{
    printf("Available commands:\n");
    printf("\t> register <username> <password>\n");
    printf("\t> login <username> <password>\n");
    printf("\t> logout\n");
    printf("\t> store <source file path> <submission name>\n");
    printf("\t> retrieve <submission name> <destination file path>\n");
    printf("\t> exit\n");
}

int main()
{
    char command[10];
    char arg1[50];
    char arg2[50];

    NTSTATUS status = GlobalDataInitialize();
    if (!NT_SUCCESS(status))
    {
        printf("GlobalDataInitialize failed with NTSTATUS = 0x%X\n", status);
        assert(FALSE);
        return -1;
    }

    PrintHelp();
    do
    {
        printf("Enter your command:\n");
        scanf("%s", command);

        if (memcmp(command, "register", sizeof("register")) == 0)
        {
            scanf("%s", arg1);    // username
            scanf("%s", arg2);    // password

            printf("register with username [%s] password [%s]\n", arg1, arg2);
            SafeStorageHandleRegister(arg1, (USHORT)strlen(arg1), arg2, (USHORT)strlen(arg2));
        }
        else if (memcmp(command, "login", sizeof("login")) == 0)
        {
            scanf("%s", arg1);    // username
            scanf("%s", arg2);    // password

            printf("login with username [%s] password [%s]\n", arg1, arg2);
            SafeStorageHandleLogin(arg1, (USHORT)strlen(arg1), arg2, (USHORT)strlen(arg2));
        }
        else if (memcmp(command, "logout", sizeof("logout")) == 0)
        {
            printf("logout\n");
            SafeStorageHandleLogout();
        }
        else if (memcmp(command, "store", sizeof("store")) == 0)
        {
            scanf("%s", arg1);    // source file path
            scanf("%s", arg2);    // submission name

            printf("store with source file path [%s] submission name [%s]\n", arg1, arg2);
            SafeStorageHandleStore(arg2, (USHORT)strlen(arg2), arg1, (USHORT)strlen(arg1));
        }
        else if (memcmp(command, "retrieve", sizeof("retrieve")) == 0)
        {
            scanf("%s", arg1);    // submission name 
            scanf("%s", arg2);    // destination file path

            printf("retrieve with submission name [%s] destination file path [%s]\n", arg1, arg2);
            SafeStorageHandleRetrieve(arg1, (USHORT)strlen(arg1), arg2, (USHORT)strlen(arg2));
        }
        else if (memcmp(command, "exit", sizeof("exit")) == 0)
        {
            printf("Bye Bye!\n");
            break;
        }
        else
        {
            printf("Unknown command. Try again!\n");
        }
    } while (TRUE);

    return 0;

我需要帮助来实现这个注册句柄功能。我可以看到这个注册函数有这两个参数Username**Password并且还定义了数据的类型。我不知道如何使用 SAL 注释编写正确的 C 声明来完成这项工作。

// Handles the "register" command
// Creates the user with Username and Password specified
//      * Creates the user's subdirectory in the %APPDIR%\users directory
// Fails if the user is already registered
// This command is available only if no user is currently logged in (it must fail otherwise)
// It returns STATUS_SUCCESS if everything succeeded or a proper error status otherwise.

_Must_inspect_result_
NTSTATUS
SafeStorageHandleRegister(
    _In_reads_bytes_opt_(UsernameLength) PCHAR Username,
    _In_ USHORT UsernameLength,
    _In_reads_bytes_opt_(PasswordLength) PCHAR Password, 
    _In_ USHORT PasswordLength);
4

1 回答 1

1

解决呼叫SafeStorageHandleRegister()

鉴于您的原始原型:

SafeStorageHandleRegister(
_In_reads_bytes_opt_(UsernameLength) PCHAR Username,
_In_ USHORT UsernameLength,
_In_reads_bytes_opt_(PasswordLength) PCHAR Password, 
_In_ USHORT PasswordLength);

一个问题是在您的电话中:

SafeStorageHandleRegister(arg1, (USHORT)strlen(arg1), arg2, (USHORT)strlen(arg2));

...参数 3 和 4 中指定的字节数不包括空字节的空间,导致字节数值不正确。 strlen()不包括\0在其计算中,但\0 位于所有 C 字符串的末尾(此处正在使用)。使用sizeof(arg1)andsizeof(arg2)代替。例如:

SafeStorageHandleRegister(arg1, (USHORT)sizeof(arg1), arg2, (USHORT)sizeof(arg2));

而且,因为如果这是您的函数原型,则sizeof宏会返回size_t(即您可以修改的原型。)我建议将其从使用USHORT更改size_t为第二个和第四个参数:

SafeStorageHandleRegister(
_In_reads_bytes_opt_(UsernameLength) PCHAR Username,
_In_ size_t UsernameLength,
_In_reads_bytes_opt_(PasswordLength) PCHAR Password, 
_In_ size_t PasswordLength);

...使其更具可读性,因为不会有演员表:

SafeStorageHandleRegister(arg1, sizeof(arg1), arg2, sizeof(arg2));

_解决 SAL 符号的潜在问题:

这可能会或可能不会导致您的失败,但无论如何都要注意......

“如果不允许调用者传入空指针,请使用_In_or_Out_代替_In_opt_or _Out_opt_。这甚至适用于检查其参数并在不应该为 NULL 时返回错误的函数。” ...

因此,例如:

// Incorrect
void Func1(_Out_opt_ int *p1)
{
    *p = 1;
}

// Correct
void Func2(_Out_ int *p1)
{
    *p = 1;
}

由于您不希望您的函数具有传递指针的选项NULL,因此最好考虑将 SAL 表示法从_In_reads_bytes_opt_to修改_In_reads_bytes_(删除该选项)

 SafeStorageHandleRegister(
_In_reads_bytes(UsernameLength) PCHAR Username,
_In_ size_t UsernameLength,
_In_reads_bytes(PasswordLength) PCHAR Password, 
_In_ size_t PasswordLength);

更多关于SAL 符号的内容。

于 2021-01-07T14:31:26.637 回答