The following issues were found

app/src/server.c
16 issues
sprintf - Potential format string problem
Security

Line: 261 Column: 5 CWE codes: 134
Suggestion: Make format string constant

                  char max_fps_string[6];
    char lock_video_orientation_string[5];
    char display_id_string[11];
    sprintf(max_size_string, "%"PRIu16, params->max_size);
    sprintf(bit_rate_string, "%"PRIu32, params->bit_rate);
    sprintf(max_fps_string, "%"PRIu16, params->max_fps);
    sprintf(lock_video_orientation_string, "%"PRIi8, params->lock_video_orientation);
    sprintf(display_id_string, "%"PRIu32, params->display_id);
    const char *const cmd[] = {

            

Reported by FlawFinder.

sprintf - Potential format string problem
Security

Line: 262 Column: 5 CWE codes: 134
Suggestion: Make format string constant

                  char lock_video_orientation_string[5];
    char display_id_string[11];
    sprintf(max_size_string, "%"PRIu16, params->max_size);
    sprintf(bit_rate_string, "%"PRIu32, params->bit_rate);
    sprintf(max_fps_string, "%"PRIu16, params->max_fps);
    sprintf(lock_video_orientation_string, "%"PRIi8, params->lock_video_orientation);
    sprintf(display_id_string, "%"PRIu32, params->display_id);
    const char *const cmd[] = {
        "shell",

            

Reported by FlawFinder.

sprintf - Potential format string problem
Security

Line: 263 Column: 5 CWE codes: 134
Suggestion: Make format string constant

                  char display_id_string[11];
    sprintf(max_size_string, "%"PRIu16, params->max_size);
    sprintf(bit_rate_string, "%"PRIu32, params->bit_rate);
    sprintf(max_fps_string, "%"PRIu16, params->max_fps);
    sprintf(lock_video_orientation_string, "%"PRIi8, params->lock_video_orientation);
    sprintf(display_id_string, "%"PRIu32, params->display_id);
    const char *const cmd[] = {
        "shell",
        "CLASSPATH=" DEVICE_SERVER_PATH,

            

Reported by FlawFinder.

sprintf - Potential format string problem
Security

Line: 264 Column: 5 CWE codes: 134
Suggestion: Make format string constant

                  sprintf(max_size_string, "%"PRIu16, params->max_size);
    sprintf(bit_rate_string, "%"PRIu32, params->bit_rate);
    sprintf(max_fps_string, "%"PRIu16, params->max_fps);
    sprintf(lock_video_orientation_string, "%"PRIi8, params->lock_video_orientation);
    sprintf(display_id_string, "%"PRIu32, params->display_id);
    const char *const cmd[] = {
        "shell",
        "CLASSPATH=" DEVICE_SERVER_PATH,
        "app_process",

            

Reported by FlawFinder.

sprintf - Potential format string problem
Security

Line: 265 Column: 5 CWE codes: 134
Suggestion: Make format string constant

                  sprintf(bit_rate_string, "%"PRIu32, params->bit_rate);
    sprintf(max_fps_string, "%"PRIu16, params->max_fps);
    sprintf(lock_video_orientation_string, "%"PRIi8, params->lock_video_orientation);
    sprintf(display_id_string, "%"PRIu32, params->display_id);
    const char *const cmd[] = {
        "shell",
        "CLASSPATH=" DEVICE_SERVER_PATH,
        "app_process",
#ifdef SERVER_DEBUGGER

            

Reported by FlawFinder.

strcpy - Does not check for buffer overflows when copying to destination [MS-banned]
Security

Line: 480 Column: 5 CWE codes: 120
Suggestion: Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)

                  buf[DEVICE_NAME_FIELD_LENGTH - 1] = '\0';
    // strcpy is safe here, since name contains at least
    // DEVICE_NAME_FIELD_LENGTH bytes and strlen(buf) < DEVICE_NAME_FIELD_LENGTH
    strcpy(device_name, (char *) buf);
    size->width = (buf[DEVICE_NAME_FIELD_LENGTH] << 8)
            | buf[DEVICE_NAME_FIELD_LENGTH + 1];
    size->height = (buf[DEVICE_NAME_FIELD_LENGTH + 2] << 8)
            | buf[DEVICE_NAME_FIELD_LENGTH + 3];
    return true;

            

Reported by FlawFinder.

getenv - Environment variables are untrustable input if they can be set by an attacker. They can have any content and length, and the same variable can be set more than once
Security

Line: 27 Column: 35 CWE codes: 807 20
Suggestion: Check environment variables carefully before using them

              #ifdef __WINDOWS__
    const wchar_t *server_path_env = _wgetenv(L"SCRCPY_SERVER_PATH");
#else
    const char *server_path_env = getenv("SCRCPY_SERVER_PATH");
#endif
    if (server_path_env) {
        // if the envvar is set, use it
#ifdef __WINDOWS__
        char *server_path = utf8_from_wide_char(server_path_env);

            

Reported by FlawFinder.

memcpy - Does not check for buffer overflows when copying to destination
Security

Line: 76 Column: 5 CWE codes: 120
Suggestion: Make sure destination can always hold the source data

                      return strdup(SERVER_FILENAME);
    }

    memcpy(server_path, dir, dirlen);
    server_path[dirlen] = PATH_SEPARATOR;
    memcpy(&server_path[dirlen + 1], SERVER_FILENAME, sizeof(SERVER_FILENAME));
    // the final null byte has been copied with SERVER_FILENAME

    free(executable_path);

            

Reported by FlawFinder.

memcpy - Does not check for buffer overflows when copying to destination
Security

Line: 78 Column: 5 CWE codes: 120
Suggestion: Make sure destination can always hold the source data

              
    memcpy(server_path, dir, dirlen);
    server_path[dirlen] = PATH_SEPARATOR;
    memcpy(&server_path[dirlen + 1], SERVER_FILENAME, sizeof(SERVER_FILENAME));
    // the final null byte has been copied with SERVER_FILENAME

    free(executable_path);

    LOGD("Using server (portable): %s", server_path);

            

Reported by FlawFinder.

char - Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues
Security

Line: 256 Column: 5 CWE codes: 119 120
Suggestion: Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length

              
static process_t
execute_server(struct server *server, const struct server_params *params) {
    char max_size_string[6];
    char bit_rate_string[11];
    char max_fps_string[6];
    char lock_video_orientation_string[5];
    char display_id_string[11];
    sprintf(max_size_string, "%"PRIu16, params->max_size);

            

Reported by FlawFinder.

app/tests/test_control_msg_serialize.c
15 issues
char - Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues
Security

Line: 19 Column: 14 CWE codes: 119 120
Suggestion: Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length

                      },
    };

    unsigned char buf[CONTROL_MSG_MAX_SIZE];
    size_t size = control_msg_serialize(&msg, buf);
    assert(size == 14);

    const unsigned char expected[] = {
        CONTROL_MSG_TYPE_INJECT_KEYCODE,

            

Reported by FlawFinder.

char - Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues
Security

Line: 41 Column: 14 CWE codes: 119 120
Suggestion: Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length

                      },
    };

    unsigned char buf[CONTROL_MSG_MAX_SIZE];
    size_t size = control_msg_serialize(&msg, buf);
    assert(size == 18);

    const unsigned char expected[] = {
        CONTROL_MSG_TYPE_INJECT_TEXT,

            

Reported by FlawFinder.

char - Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues
Security

Line: 56 Column: 5 CWE codes: 119 120
Suggestion: Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length

              static void test_serialize_inject_text_long(void) {
    struct control_msg msg;
    msg.type = CONTROL_MSG_TYPE_INJECT_TEXT;
    char text[CONTROL_MSG_INJECT_TEXT_MAX_LENGTH + 1];
    memset(text, 'a', sizeof(text));
    text[CONTROL_MSG_INJECT_TEXT_MAX_LENGTH] = '\0';
    msg.inject_text.text = text;

    unsigned char buf[CONTROL_MSG_MAX_SIZE];

            

Reported by FlawFinder.

char - Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues
Security

Line: 61 Column: 14 CWE codes: 119 120
Suggestion: Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length

                  text[CONTROL_MSG_INJECT_TEXT_MAX_LENGTH] = '\0';
    msg.inject_text.text = text;

    unsigned char buf[CONTROL_MSG_MAX_SIZE];
    size_t size = control_msg_serialize(&msg, buf);
    assert(size == 5 + CONTROL_MSG_INJECT_TEXT_MAX_LENGTH);

    unsigned char expected[5 + CONTROL_MSG_INJECT_TEXT_MAX_LENGTH];
    expected[0] = CONTROL_MSG_TYPE_INJECT_TEXT;

            

Reported by FlawFinder.

char - Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues
Security

Line: 65 Column: 14 CWE codes: 119 120
Suggestion: Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length

                  size_t size = control_msg_serialize(&msg, buf);
    assert(size == 5 + CONTROL_MSG_INJECT_TEXT_MAX_LENGTH);

    unsigned char expected[5 + CONTROL_MSG_INJECT_TEXT_MAX_LENGTH];
    expected[0] = CONTROL_MSG_TYPE_INJECT_TEXT;
    expected[1] = 0x00;
    expected[2] = 0x00;
    expected[3] = 0x01;
    expected[4] = 0x2c; // text length (32 bits)

            

Reported by FlawFinder.

char - Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues
Security

Line: 97 Column: 14 CWE codes: 119 120
Suggestion: Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length

                      },
    };

    unsigned char buf[CONTROL_MSG_MAX_SIZE];
    size_t size = control_msg_serialize(&msg, buf);
    assert(size == 28);

    const unsigned char expected[] = {
        CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT,

            

Reported by FlawFinder.

char - Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues
Security

Line: 132 Column: 14 CWE codes: 119 120
Suggestion: Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length

                      },
    };

    unsigned char buf[CONTROL_MSG_MAX_SIZE];
    size_t size = control_msg_serialize(&msg, buf);
    assert(size == 21);

    const unsigned char expected[] = {
        CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT,

            

Reported by FlawFinder.

char - Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues
Security

Line: 154 Column: 14 CWE codes: 119 120
Suggestion: Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length

                      },
    };

    unsigned char buf[CONTROL_MSG_MAX_SIZE];
    size_t size = control_msg_serialize(&msg, buf);
    assert(size == 2);

    const unsigned char expected[] = {
        CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON,

            

Reported by FlawFinder.

char - Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues
Security

Line: 170 Column: 14 CWE codes: 119 120
Suggestion: Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length

                      .type = CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL,
    };

    unsigned char buf[CONTROL_MSG_MAX_SIZE];
    size_t size = control_msg_serialize(&msg, buf);
    assert(size == 1);

    const unsigned char expected[] = {
        CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL,

            

Reported by FlawFinder.

char - Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues
Security

Line: 185 Column: 14 CWE codes: 119 120
Suggestion: Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length

                      .type = CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL,
    };

    unsigned char buf[CONTROL_MSG_MAX_SIZE];
    size_t size = control_msg_serialize(&msg, buf);
    assert(size == 1);

    const unsigned char expected[] = {
        CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL,

            

Reported by FlawFinder.

app/src/adb.c
14 issues
sprintf - Potential format string problem
Security

Line: 147 Column: 5 CWE codes: 134
Suggestion: Make format string constant

                          const char *device_socket_name) {
    char local[4 + 5 + 1]; // tcp:PORT
    char remote[108 + 14 + 1]; // localabstract:NAME
    sprintf(local, "tcp:%" PRIu16, local_port);
    snprintf(remote, sizeof(remote), "localabstract:%s", device_socket_name);
    const char *const adb_cmd[] = {"forward", local, remote};
    return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
}


            

Reported by FlawFinder.

sprintf - Potential format string problem
Security

Line: 156 Column: 5 CWE codes: 134
Suggestion: Make format string constant

              process_t
adb_forward_remove(const char *serial, uint16_t local_port) {
    char local[4 + 5 + 1]; // tcp:PORT
    sprintf(local, "tcp:%" PRIu16, local_port);
    const char *const adb_cmd[] = {"forward", "--remove", local};
    return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
}

process_t

            

Reported by FlawFinder.

sprintf - Potential format string problem
Security

Line: 166 Column: 5 CWE codes: 134
Suggestion: Make format string constant

                          uint16_t local_port) {
    char local[4 + 5 + 1]; // tcp:PORT
    char remote[108 + 14 + 1]; // localabstract:NAME
    sprintf(local, "tcp:%" PRIu16, local_port);
    snprintf(remote, sizeof(remote), "localabstract:%s", device_socket_name);
    const char *const adb_cmd[] = {"reverse", remote, local};
    return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
}


            

Reported by FlawFinder.

getenv - Environment variables are untrustable input if they can be set by an attacker. They can have any content and length, and the same variable can be set more than once
Security

Line: 16 Column: 23 CWE codes: 807 20
Suggestion: Check environment variables carefully before using them

              static inline const char *
get_adb_command(void) {
    if (!adb_command) {
        adb_command = getenv("ADB");
        if (!adb_command)
            adb_command = "adb";
    }
    return adb_command;
}

            

Reported by FlawFinder.

memcpy - Does not check for buffer overflows when copying to destination
Security

Line: 35 Column: 13 CWE codes: 120
Suggestion: Make sure destination can always hold the source data

                      if (idx + len + 8 >= bufsize) {
            // not enough space, truncate
            assert(idx < bufsize - 4);
            memcpy(&buf[idx], "...", 3);
            idx += 3;
            break;
        }
        if (first) {
            first = false;

            

Reported by FlawFinder.

memcpy - Does not check for buffer overflows when copying to destination
Security

Line: 46 Column: 9 CWE codes: 120
Suggestion: Make sure destination can always hold the source data

                          buf[idx++] = ' ';
        }
        buf[idx++] = '[';
        memcpy(&buf[idx], arg, len);
        idx += len;
        buf[idx++] = ']';
        argv++;
    }
    assert(idx < bufsize);

            

Reported by FlawFinder.

memcpy - Does not check for buffer overflows when copying to destination
Security

Line: 130 Column: 5 CWE codes: 120
Suggestion: Make sure destination can always hold the source data

                      i = 1;
    }

    memcpy(&argv[i], adb_cmd, len * sizeof(const char *));
    argv[len + i] = NULL;
    enum process_result r = process_execute(argv, &process);
    if (r != PROCESS_SUCCESS) {
        show_adb_err_msg(r, argv);
        process = PROCESS_NONE;

            

Reported by FlawFinder.

char - Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues
Security

Line: 145 Column: 5 CWE codes: 119 120
Suggestion: Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length

              process_t
adb_forward(const char *serial, uint16_t local_port,
            const char *device_socket_name) {
    char local[4 + 5 + 1]; // tcp:PORT
    char remote[108 + 14 + 1]; // localabstract:NAME
    sprintf(local, "tcp:%" PRIu16, local_port);
    snprintf(remote, sizeof(remote), "localabstract:%s", device_socket_name);
    const char *const adb_cmd[] = {"forward", local, remote};
    return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));

            

Reported by FlawFinder.

char - Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues
Security

Line: 146 Column: 5 CWE codes: 119 120
Suggestion: Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length

              adb_forward(const char *serial, uint16_t local_port,
            const char *device_socket_name) {
    char local[4 + 5 + 1]; // tcp:PORT
    char remote[108 + 14 + 1]; // localabstract:NAME
    sprintf(local, "tcp:%" PRIu16, local_port);
    snprintf(remote, sizeof(remote), "localabstract:%s", device_socket_name);
    const char *const adb_cmd[] = {"forward", local, remote};
    return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
}

            

Reported by FlawFinder.

char - Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues
Security

Line: 155 Column: 5 CWE codes: 119 120
Suggestion: Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length

              
process_t
adb_forward_remove(const char *serial, uint16_t local_port) {
    char local[4 + 5 + 1]; // tcp:PORT
    sprintf(local, "tcp:%" PRIu16, local_port);
    const char *const adb_cmd[] = {"forward", "--remove", local};
    return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
}


            

Reported by FlawFinder.

app/src/sys/unix/process.c
9 issues
readlink - This accepts filename arguments; if an attacker can move those files or change the link content, a race condition results. Also, it does not terminate with ASCII NUL.
Security

Line: 153 Column: 19 CWE codes: 362 20
Suggestion: Reconsider approach

              // <https://stackoverflow.com/a/1024937/1987178>
#ifdef __linux__
    char buf[PATH_MAX + 1]; // +1 for the null byte
    ssize_t len = readlink("/proc/self/exe", buf, PATH_MAX);
    if (len == -1) {
        perror("readlink");
        return NULL;
    }
    buf[len] = '\0';

            

Reported by FlawFinder.

execvp - This causes a new program to execute and is difficult to use safely
Security

Line: 84 Column: 13 CWE codes: 78
Suggestion: try using a library call that implements the same functionality if available

                      // child close read side
        close(fd[0]);
        if (fcntl(fd[1], F_SETFD, FD_CLOEXEC) == 0) {
            execvp(argv[0], (char *const *)argv);
            if (errno == ENOENT) {
                ret = PROCESS_ERROR_MISSING_BINARY;
            } else {
                ret = PROCESS_ERROR_GENERIC;
            }

            

Reported by FlawFinder.

getenv - Environment variables are untrustable input if they can be set by an attacker. They can have any content and length, and the same variable can be set more than once
Security

Line: 18 Column: 18 CWE codes: 807 20
Suggestion: Check environment variables carefully before using them

              
bool
search_executable(const char *file) {
    char *path = getenv("PATH");
    if (!path)
        return false;
    path = strdup(path);
    if (!path)
        return false;

            

Reported by FlawFinder.

memcpy - Does not check for buffer overflows when copying to destination
Security

Line: 34 Column: 9 CWE codes: 120
Suggestion: Make sure destination can always hold the source data

                      char *fullpath = malloc(dir_len + file_len + 2);
        if (!fullpath)
            continue;
        memcpy(fullpath, dir, dir_len);
        fullpath[dir_len] = '/';
        memcpy(fullpath + dir_len + 1, file, file_len + 1);

        struct stat sb;
        bool fullpath_executable = stat(fullpath, &sb) == 0 &&

            

Reported by FlawFinder.

memcpy - Does not check for buffer overflows when copying to destination
Security

Line: 36 Column: 9 CWE codes: 120
Suggestion: Make sure destination can always hold the source data

                          continue;
        memcpy(fullpath, dir, dir_len);
        fullpath[dir_len] = '/';
        memcpy(fullpath + dir_len + 1, file, file_len + 1);

        struct stat sb;
        bool fullpath_executable = stat(fullpath, &sb) == 0 &&
            sb.st_mode & S_IXUSR;
        free(fullpath);

            

Reported by FlawFinder.

char - Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues
Security

Line: 152 Column: 5 CWE codes: 119 120
Suggestion: Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length

              get_executable_path(void) {
// <https://stackoverflow.com/a/1024937/1987178>
#ifdef __linux__
    char buf[PATH_MAX + 1]; // +1 for the null byte
    ssize_t len = readlink("/proc/self/exe", buf, PATH_MAX);
    if (len == -1) {
        perror("readlink");
        return NULL;
    }

            

Reported by FlawFinder.

strlen - Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected)
Security

Line: 26 Column: 23 CWE codes: 126

                      return false;

    bool ret = false;
    size_t file_len = strlen(file);
    char *saveptr;
    for (char *dir = strtok_r(path, ":", &saveptr); dir;
            dir = strtok_r(NULL, ":", &saveptr)) {
        size_t dir_len = strlen(dir);
        char *fullpath = malloc(dir_len + file_len + 2);

            

Reported by FlawFinder.

strlen - Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected)
Security

Line: 30 Column: 26 CWE codes: 126

                  char *saveptr;
    for (char *dir = strtok_r(path, ":", &saveptr); dir;
            dir = strtok_r(NULL, ":", &saveptr)) {
        size_t dir_len = strlen(dir);
        char *fullpath = malloc(dir_len + file_len + 2);
        if (!fullpath)
            continue;
        memcpy(fullpath, dir, dir_len);
        fullpath[dir_len] = '/';

            

Reported by FlawFinder.

read - Check buffer boundaries if used in a loop including recursive loops
Security

Line: 75 Column: 13 CWE codes: 120 20

                      close(fd[1]);
        fd[1] = -1;
        // wait for EOF or receive errno from child
        if (read(fd[0], &ret, sizeof(ret)) == -1) {
            perror("read");
            ret = PROCESS_ERROR_GENERIC;
            goto end;
        }
    } else if (*pid == 0) {

            

Reported by FlawFinder.

app/tests/test_strutil.c
6 issues
char - Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues
Security

Line: 269 Column: 5 CWE codes: 119 120
Suggestion: Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length

                  ok = parse_integer_with_suffix("123456789876543212345678987654321", &value);
    assert(!ok); // out-of-range

    char buf[32];

    sprintf(buf, "%ldk", LONG_MAX / 2000);
    ok = parse_integer_with_suffix(buf, &value);
    assert(ok);
    assert(value == LONG_MAX / 2000 * 1000);

            

Reported by FlawFinder.

sprintf - Does not check for buffer overflows
Security

Line: 271 Column: 5 CWE codes: 120
Suggestion: Use sprintf_s, snprintf, or vsnprintf

              
    char buf[32];

    sprintf(buf, "%ldk", LONG_MAX / 2000);
    ok = parse_integer_with_suffix(buf, &value);
    assert(ok);
    assert(value == LONG_MAX / 2000 * 1000);

    sprintf(buf, "%ldm", LONG_MAX / 2000);

            

Reported by FlawFinder.

sprintf - Does not check for buffer overflows
Security

Line: 276 Column: 5 CWE codes: 120
Suggestion: Use sprintf_s, snprintf, or vsnprintf

                  assert(ok);
    assert(value == LONG_MAX / 2000 * 1000);

    sprintf(buf, "%ldm", LONG_MAX / 2000);
    ok = parse_integer_with_suffix(buf, &value);
    assert(!ok);

    sprintf(buf, "%ldk", LONG_MIN / 2000);
    ok = parse_integer_with_suffix(buf, &value);

            

Reported by FlawFinder.

sprintf - Does not check for buffer overflows
Security

Line: 280 Column: 5 CWE codes: 120
Suggestion: Use sprintf_s, snprintf, or vsnprintf

                  ok = parse_integer_with_suffix(buf, &value);
    assert(!ok);

    sprintf(buf, "%ldk", LONG_MIN / 2000);
    ok = parse_integer_with_suffix(buf, &value);
    assert(ok);
    assert(value == LONG_MIN / 2000 * 1000);

    sprintf(buf, "%ldm", LONG_MIN / 2000);

            

Reported by FlawFinder.

sprintf - Does not check for buffer overflows
Security

Line: 285 Column: 5 CWE codes: 120
Suggestion: Use sprintf_s, snprintf, or vsnprintf

                  assert(ok);
    assert(value == LONG_MIN / 2000 * 1000);

    sprintf(buf, "%ldm", LONG_MIN / 2000);
    ok = parse_integer_with_suffix(buf, &value);
    assert(!ok);
}

static void test_strlist_contains(void) {

            

Reported by FlawFinder.

strlen - Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected)
Security

Line: 145 Column: 12 CWE codes: 126

              
static void test_utf8_truncate(void) {
    const char *s = "aÉbÔc";
    assert(strlen(s) == 7); // É and Ô are 2 bytes-wide

    size_t count;

    count = utf8_truncation_index(s, 1);
    assert(count == 1);

            

Reported by FlawFinder.

app/src/util/str_util.c
6 issues
memcpy - Does not check for buffer overflows when copying to destination
Security

Line: 54 Column: 5 CWE codes: 120
Suggestion: Make sure destination can always hold the source data

                  if (!quoted) {
        return NULL;
    }
    memcpy(&quoted[1], src, len);
    quoted[0] = '"';
    quoted[len + 1] = '"';
    quoted[len + 2] = '\0';
    return quoted;
}

            

Reported by FlawFinder.

MultiByteToWideChar - Requires maximum length in CHARACTERS, not bytes
Security

Line: 181 Column: 15 CWE codes: 120

              
wchar_t *
utf8_to_wide_char(const char *utf8) {
    int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
    if (!len) {
        return NULL;
    }

    wchar_t *wide = malloc(len * sizeof(wchar_t));

            

Reported by FlawFinder.

MultiByteToWideChar - Requires maximum length in CHARACTERS, not bytes
Security

Line: 191 Column: 5 CWE codes: 120

                      return NULL;
    }

    MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wide, len);
    return wide;
}

char *
utf8_from_wide_char(const wchar_t *ws) {

            

Reported by FlawFinder.

strlen - Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected)
Security

Line: 49 Column: 18 CWE codes: 126

              
char *
strquote(const char *src) {
    size_t len = strlen(src);
    char *quoted = malloc(len + 3);
    if (!quoted) {
        return NULL;
    }
    memcpy(&quoted[1], src, len);

            

Reported by FlawFinder.

strlen - Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected)
Security

Line: 149 Column: 54 CWE codes: 126

                  do {
        p = strchr(list, sep);

        size_t token_len = p ? (size_t) (p - list) : strlen(list);
        if (!strncmp(list, s, token_len)) {
            return true;
        }

        if (p) {

            

Reported by FlawFinder.

strlen - Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected)
Security

Line: 163 Column: 18 CWE codes: 126

              
size_t
utf8_truncation_index(const char *utf8, size_t max_len) {
    size_t len = strlen(utf8);
    if (len <= max_len) {
        return len;
    }
    len = max_len;
    // see UTF-8 encoding <https://en.wikipedia.org/wiki/UTF-8#Description>

            

Reported by FlawFinder.

app/src/scrcpy.c
4 issues
memcpy - Does not check for buffer overflows when copying to destination
Security

Line: 226 Column: 5 CWE codes: 120
Suggestion: Make sure destination can always hold the source data

                      LOGC("Could not allocate string");
        return;
    }
    memcpy(local_fmt, "[FFmpeg] ", 9); // do not write the final '\0'
    memcpy(local_fmt + 9, fmt, fmt_len + 1); // include '\0'
    SDL_LogMessageV(SDL_LOG_CATEGORY_VIDEO, priority, local_fmt, vl);
    free(local_fmt);
}


            

Reported by FlawFinder.

memcpy - Does not check for buffer overflows when copying to destination
Security

Line: 227 Column: 5 CWE codes: 120
Suggestion: Make sure destination can always hold the source data

                      return;
    }
    memcpy(local_fmt, "[FFmpeg] ", 9); // do not write the final '\0'
    memcpy(local_fmt + 9, fmt, fmt_len + 1); // include '\0'
    SDL_LogMessageV(SDL_LOG_CATEGORY_VIDEO, priority, local_fmt, vl);
    free(local_fmt);
}

static void

            

Reported by FlawFinder.

char - Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues
Security

Line: 294 Column: 5 CWE codes: 119 120
Suggestion: Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length

                      goto end;
    }

    char device_name[DEVICE_NAME_FIELD_LENGTH];
    struct size frame_size;

    if (!server_connect_to(&s->server, device_name, &frame_size)) {
        goto end;
    }

            

Reported by FlawFinder.

strlen - Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected)
Security

Line: 220 Column: 22 CWE codes: 126

                      return;
    }

    size_t fmt_len = strlen(fmt);
    char *local_fmt = malloc(fmt_len + 10);
    if (!local_fmt) {
        LOGC("Could not allocate string");
        return;
    }

            

Reported by FlawFinder.

app/src/cli.c
3 issues
getopt_long - Some older implementations do not protect against internal buffer overflows
Security

Line: 755 Column: 17 CWE codes: 120 20
Suggestion: Check implementation on installation, or limit the size of all string inputs

                  optind = 0; // reset to start from the first argument in tests

    int c;
    while ((c = getopt_long(argc, argv, "b:c:fF:hm:nNp:r:s:StTvV:w",
                            long_options, NULL)) != -1) {
        switch (c) {
            case 'b':
                if (!parse_bit_rate(optarg, &opts->bit_rate)) {
                    return false;

            

Reported by FlawFinder.

strlen - Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected)
Security

Line: 603 Column: 55 CWE codes: 126

                      }

        assert(!comma || comma > s);
        size_t limit = comma ? (size_t) (comma - s) : strlen(s);

        unsigned mod = parse_shortcut_mods_item(s, limit);
        if (!mod) {
            LOGE("Invalid modifier keys: %.*s", (int) limit, s);
            return false;

            

Reported by FlawFinder.

strlen - Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected)
Security

Line: 650 Column: 18 CWE codes: 126

              
static enum sc_record_format
guess_record_format(const char *filename) {
    size_t len = strlen(filename);
    if (len < 4) {
        return 0;
    }
    const char *ext = &filename[len - 4];
    if (!strcmp(ext, ".mp4")) {

            

Reported by FlawFinder.

app/src/file_handler.c
3 issues
Uninitialized struct member: req.action
Error

Line: 127 CWE codes: 908

                      (void) non_empty;

        process_t process;
        if (req.action == ACTION_INSTALL_APK) {
            LOGI("Installing %s...", req.file);
            process = install_apk(file_handler->serial, req.file);
        } else {
            LOGI("Pushing %s...", req.file);
            process = push_file(file_handler->serial, req.file,

            

Reported by Cppcheck.

Uninitialized variable: action
Error

Line: 127 CWE codes: 908

                      (void) non_empty;

        process_t process;
        if (req.action == ACTION_INSTALL_APK) {
            LOGI("Installing %s...", req.file);
            process = install_apk(file_handler->serial, req.file);
        } else {
            LOGI("Pushing %s...", req.file);
            process = push_file(file_handler->serial, req.file,

            

Reported by Cppcheck.

Uninitialized struct member: req.action
Error

Line: 138 CWE codes: 908

                      file_handler->current_process = process;
        sc_mutex_unlock(&file_handler->mutex);

        if (req.action == ACTION_INSTALL_APK) {
            if (process_check_success(process, "adb install", false)) {
                LOGI("%s successfully installed", req.file);
            } else {
                LOGE("Failed to install %s", req.file);
            }

            

Reported by Cppcheck.

app/src/stream.c
2 issues
memcpy - Does not check for buffer overflows when copying to destination
Security

Line: 131 Column: 9 CWE codes: 120
Suggestion: Make sure destination can always hold the source data

                          }
        }

        memcpy(stream->pending->data + offset, packet->data, packet->size);

        if (!is_config) {
            // prepare the concat packet to send to the decoder
            stream->pending->pts = packet->pts;
            stream->pending->dts = packet->dts;

            

Reported by FlawFinder.

open - Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents?
Security

Line: 182 Column: 25 CWE codes: 362

              stream_open_sinks(struct stream *stream, const AVCodec *codec) {
    for (unsigned i = 0; i < stream->sink_count; ++i) {
        struct sc_packet_sink *sink = stream->sinks[i];
        if (!sink->ops->open(sink, codec)) {
            LOGE("Could not open packet sink %d", i);
            stream_close_first_sinks(stream, i);
            return false;
        }
    }

            

Reported by FlawFinder.