A potential Integer Overflow bug found in aplay/aplay.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



alsa-project/alsa-utils issue #231 was opened from cascades-sjtu:

Hi, I'm currently trying to use the static analysis tool [Infer](https://fbinfer.com) to find uncatched API-misuse bugs in OpenWrt packages, and I find a potential Integer Overflow  in your project, version 1.2.9.

The bug located in aplay/aplay.c. Firstly, the program tries to write the remains bytes in `audiobuf` with the length of `loaded` in line 2865, and `loaded` is later used as the parameter for `safe_read` in the loop, then `loaded` is used as the 2nd argument of `pct_write()` and finally after a multiply operation, it is used as the size of Malloc in `remap_data()`, as shown in the following code:

```cpp
static void playback_go(int fd, size_t loaded, off_t count, int rtype, char *name)
{
int l, r;
off_t written = 0;
off_t c;

header(rtype, name);
set_params();

while (loaded > chunk_bytes && written < count && !in_aborting) {
	if (pcm_write(audiobuf + written, chunk_size) <= 0)
		return;
	written += chunk_bytes;
	loaded -= chunk_bytes;
}
if (written > 0 && loaded > 0)
	memmove(audiobuf, audiobuf + written, loaded);

l = loaded;
while (written < count && !in_aborting) {
	do {
		c = count - written;
		if (c > chunk_bytes)
			c = chunk_bytes;

		/* c < l, there is more data loaded
			* then we actually need to write
			*/
		if (c < l)
			l = c;

		c -= l;

		if (c == 0)
			break;
		r = safe_read(fd, audiobuf + l, c);
		if (r < 0) {
			perror(name);
			prg_exit(EXIT_FAILURE);
		}
		fdcount += r;
		if (r == 0)
			break;
		l += r;
	} while ((size_t)l < chunk_bytes);
	l = l * 8 / bits_per_frame;
	r = pcm_write(audiobuf, l);
	if (r != l)
		break;
	r = r * bits_per_frame / 8;
	written += r;
	l = 0;
}
if (!in_aborting) {
	snd_pcm_nonblock(handle, 0);
	snd_pcm_drain(handle);
	snd_pcm_nonblock(handle, nonblock);
}
}

# in remap_data()
chunk_bytes = count * bits_per_frame / 8;
if (tmp_size < chunk_bytes) {
	free(tmp);
	tmp = malloc(chunk_bytes);
	if (!tmp) {
		error(_("not enough memory"));
		exit(1);
	}
	tmp_size = count;
}
```

The parameter passed to Malloc may be overflowed so that the actual allocated memory is small. 

I also attached the analysis trace given by Infer FYI:

```json
        "trace": [
          {
            "file": "aplay/aplay.c",
            "line": 940,
            "col": 14,
            "feature": [ "Input", "read" ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 940,
            "col": 14,
            "feature": [ "Input", "read" ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2865,
            "col": 21,
            "feature": [
              "Prune",
              [
                "UnOp",
                "!",
                [
                  "BinOp",
                  ">",
                  [ "Var" ],
                  [ "Cast", [ "Unsupported" ], [ "Const", [ "Cint", 0 ] ] ]
                ]
              ]
            ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2868,
            "col": 2,
            "feature": [ "Store", [ "Var" ], [ "Var" ] ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2878,
            "col": 8,
            "feature": [
              "Prune",
              [ "UnOp", "!", [ "BinOp", "<", [ "Var" ], [ "Var" ] ] ]
            ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2871,
            "col": 4,
            "feature": [
              "Store",
              [ "Var" ],
              [ "BinOp", "-", [ "Var" ], [ "Var" ] ]
            ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2872,
            "col": 8,
            "feature": [
              "Prune",
              [
                "UnOp",
                "!",
                [
                  "BinOp",
                  ">",
                  [ "Cast", [ "Unsupported" ], [ "Var" ] ],
                  [ "Var" ]
                ]
              ]
            ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2878,
            "col": 8,
            "feature": [ "Prune", [ "BinOp", "<", [ "Var" ], [ "Var" ] ] ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2879,
            "col": 5,
            "feature": [ "Store", [ "Var" ], [ "Var" ] ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2899,
            "col": 3,
            "feature": [
              "Store",
              [ "Var" ],
              [
                "BinOp",
                "/",
                [
                  "BinOp",
                  "*",
                  [ "Cast", [ "Unsupported" ], [ "Var" ] ],
                  [ "Var" ]
                ],
                [ "Cast", [ "Unsupported" ], [ "Const", [ "Cint", 8 ] ] ]
              ]
            ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2900,
            "col": 3,
            "feature": [
              "Store",
              [ "Var" ],
              [ "BinOp", "+", [ "Var" ], [ "Var" ] ]
            ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2871,
            "col": 4,
            "feature": [
              "Store",
              [ "Var" ],
              [ "BinOp", "-", [ "Var" ], [ "Var" ] ]
            ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2872,
            "col": 8,
            "feature": [
              "Prune",
              [
                "UnOp",
                "!",
                [
                  "BinOp",
                  ">",
                  [ "Cast", [ "Unsupported" ], [ "Var" ] ],
                  [ "Var" ]
                ]
              ]
            ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2878,
            "col": 8,
            "feature": [ "Prune", [ "BinOp", "<", [ "Var" ], [ "Var" ] ] ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2879,
            "col": 5,
            "feature": [ "Store", [ "Var" ], [ "Var" ] ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2895,
            "col": 3,
            "feature": [
              "Store",
              [ "Var" ],
              [
                "BinOp",
                "/",
                [
                  "Cast",
                  [ "Unsupported" ],
                  [ "BinOp", "*", [ "Var" ], [ "Const", [ "Cint", 8 ] ] ]
                ],
                [ "Var" ]
              ]
            ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2896,
            "col": 7,
            "feature": [ "Call", "pcm_write" ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2126,
            "col": 6,
            "feature": [
              "Prune",
              [ "UnOp", "!", [ "BinOp", "<", [ "Var" ], [ "Var" ] ] ]
            ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2130,
            "col": 9,
            "feature": [ "Call", "remap_data" ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2069,
            "col": 2,
            "feature": [
              "Store",
              [ "Var" ],
              [
                "BinOp",
                "/",
                [ "BinOp", "*", [ "Var" ], [ "Var" ] ],
                [ "Cast", [ "Unsupported" ], [ "Const", [ "Cint", 8 ] ] ]
              ]
            ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2070,
            "col": 6,
            "feature": [ "Prune", [ "BinOp", "<", [ "Var" ], [ "Var" ] ] ]
          },
          {
            "file": "aplay/aplay.c",
            "line": 2072,
            "col": 9,
            "feature": [ "IntOverflow", "malloc", [ "Var" ] ]
          }
        ],
```

Issue URL     : https://github.com/alsa-project/alsa-utils/issues/231
Repository URL: https://github.com/alsa-project/alsa-utils



[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Pulse Audio]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux