Skip to content

Commit 0ab6c14

Browse files
YouwMegamouse
andauthored
Add missing sanity checks (#727)
Based on #696 - Add missing checks for zero/null arguments; - Better management of error strings in case of failures; --------- Co-authored-by: Megamouse <studienricky89@googlemail.com>
1 parent 95e6b98 commit 0ab6c14

File tree

4 files changed

+117
-19
lines changed

4 files changed

+117
-19
lines changed

libusb/hid.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ static int return_data(hid_device *dev, unsigned char *data, size_t length);
139139
static hid_device *new_hid_device(void)
140140
{
141141
hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
142+
if (!dev)
143+
return NULL;
144+
142145
dev->blocking = 1;
143146

144147
hidapi_thread_state_init(&dev->thread_state);

linux/hid.c

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -402,8 +402,8 @@ static int get_next_hid_usage(const __u8 *report_descriptor, __u32 size, struct
402402
/* If no top-level application collection is found and usage page/usage pair is found, pair is valid
403403
https://docs.microsoft.com/en-us/windows-hardware/drivers/hid/top-level-collections */
404404
if (initial && usage_found && ctx->usage_page_found) {
405-
*usage_page = ctx->usage_page;
406-
return 0; /* success */
405+
*usage_page = ctx->usage_page;
406+
return 0; /* success */
407407
}
408408

409409
return 1; /* finished processing */
@@ -448,6 +448,8 @@ static int get_hid_report_descriptor_from_sysfs(const char *sysfs_path, struct h
448448
/* Construct <sysfs_path>/device/report_descriptor */
449449
size_t rpt_path_len = strlen(sysfs_path) + 25 + 1;
450450
char* rpt_path = (char*) calloc(1, rpt_path_len);
451+
if (!rpt_path)
452+
return -1;
451453
snprintf(rpt_path, rpt_path_len, "%s/device/report_descriptor", sysfs_path);
452454

453455
res = get_hid_report_descriptor(rpt_path, rpt_desc);
@@ -784,7 +786,14 @@ static struct hid_device_info * create_device_info_for_device(struct udev_device
784786
}
785787

786788
/* Usage Page and Usage */
787-
result = get_hid_report_descriptor_from_sysfs(sysfs_path, &report_desc);
789+
790+
if (sysfs_path) {
791+
result = get_hid_report_descriptor_from_sysfs(sysfs_path, &report_desc);
792+
}
793+
else {
794+
result = -1;
795+
}
796+
788797
if (result >= 0) {
789798
unsigned short page = 0, usage = 0;
790799
struct hid_usage_iterator usage_iterator;
@@ -809,7 +818,7 @@ static struct hid_device_info * create_device_info_for_device(struct udev_device
809818
struct hid_device_info *prev_dev = cur_dev;
810819

811820
if (!tmp)
812-
continue;
821+
break;
813822
cur_dev->next = tmp;
814823
cur_dev = tmp;
815824

@@ -854,6 +863,7 @@ static struct hid_device_info * create_device_info_for_hid_device(hid_device *de
854863
/* Create the udev object */
855864
udev = udev_new();
856865
if (!udev) {
866+
errno = ENOMEM;
857867
register_device_error(dev, "Couldn't create udev context");
858868
return NULL;
859869
}
@@ -866,6 +876,7 @@ static struct hid_device_info * create_device_info_for_hid_device(hid_device *de
866876

867877
if (!root) {
868878
/* TODO: have a better error reporting via create_device_info_for_device */
879+
errno = EIO;
869880
register_device_error(dev, "Couldn't create hid_device_info");
870881
}
871882

@@ -1061,6 +1072,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path)
10611072

10621073
dev = new_hid_device();
10631074
if (!dev) {
1075+
errno = ENOMEM;
10641076
register_global_error("Couldn't allocate memory");
10651077
return NULL;
10661078
}
@@ -1073,8 +1085,8 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path)
10731085
/* Make sure this is a HIDRAW device - responds to HIDIOCGRDESCSIZE */
10741086
res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size);
10751087
if (res < 0) {
1076-
hid_close(dev);
10771088
register_global_error_format("ioctl(GRDESCSIZE) error for '%s', not a HIDRAW device?: %s", path, strerror(errno));
1089+
hid_close(dev);
10781090
return NULL;
10791091
}
10801092

@@ -1095,7 +1107,7 @@ int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t
10951107

10961108
if (!data || (length == 0)) {
10971109
errno = EINVAL;
1098-
register_device_error(dev, strerror(errno));
1110+
register_device_error(dev, "Zero buffer/length");
10991111
return -1;
11001112
}
11011113

@@ -1109,6 +1121,12 @@ int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t
11091121

11101122
int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
11111123
{
1124+
if (!data || (length == 0)) {
1125+
errno = EINVAL;
1126+
register_error_str(&dev->last_read_error_str, "Zero buffer/length");
1127+
return -1;
1128+
}
1129+
11121130
/* Set device error to none */
11131131
register_error_str(&dev->last_read_error_str, NULL);
11141132

@@ -1142,6 +1160,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
11421160
indicate a device disconnection. */
11431161
if (fds.revents & (POLLERR | POLLHUP | POLLNVAL)) {
11441162
// We cannot use strerror() here as no -1 was returned from poll().
1163+
errno = EIO;
11451164
register_error_str(&dev->last_read_error_str, "hid_read_timeout: unexpected poll error (device disconnected)");
11461165
return -1;
11471166
}
@@ -1186,6 +1205,12 @@ int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char
11861205
{
11871206
int res;
11881207

1208+
if (!data || (length == 0)) {
1209+
errno = EINVAL;
1210+
register_device_error(dev, "Zero buffer/length");
1211+
return -1;
1212+
}
1213+
11891214
register_device_error(dev, NULL);
11901215

11911216
res = ioctl(dev->device_handle, HIDIOCSFEATURE(length), data);
@@ -1199,6 +1224,12 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data,
11991224
{
12001225
int res;
12011226

1227+
if (!data || (length == 0)) {
1228+
errno = EINVAL;
1229+
register_device_error(dev, "Zero buffer/length");
1230+
return -1;
1231+
}
1232+
12021233
register_device_error(dev, NULL);
12031234

12041235
res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data);
@@ -1212,6 +1243,12 @@ int HID_API_EXPORT HID_API_CALL hid_send_output_report(hid_device *dev, const un
12121243
{
12131244
int res;
12141245

1246+
if (!data || (length == 0)) {
1247+
errno = EINVAL;
1248+
register_device_error(dev, "Zero buffer/length");
1249+
return -1;
1250+
}
1251+
12151252
register_device_error(dev, NULL);
12161253

12171254
res = ioctl(dev->device_handle, HIDIOCSOUTPUT(length), data);
@@ -1225,6 +1262,12 @@ int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned c
12251262
{
12261263
int res;
12271264

1265+
if (!data || (length == 0)) {
1266+
errno = EINVAL;
1267+
register_device_error(dev, "Zero buffer/length");
1268+
return -1;
1269+
}
1270+
12281271
register_device_error(dev, NULL);
12291272

12301273
res = ioctl(dev->device_handle, HIDIOCGINPUT(length), data);
@@ -1253,6 +1296,7 @@ void HID_API_EXPORT hid_close(hid_device *dev)
12531296
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
12541297
{
12551298
if (!string || !maxlen) {
1299+
errno = EINVAL;
12561300
register_device_error(dev, "Zero buffer/length");
12571301
return -1;
12581302
}
@@ -1277,6 +1321,7 @@ int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *st
12771321
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
12781322
{
12791323
if (!string || !maxlen) {
1324+
errno = EINVAL;
12801325
register_device_error(dev, "Zero buffer/length");
12811326
return -1;
12821327
}
@@ -1301,6 +1346,7 @@ int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string,
13011346
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
13021347
{
13031348
if (!string || !maxlen) {
1349+
errno = EINVAL;
13041350
register_device_error(dev, "Zero buffer/length");
13051351
return -1;
13061352
}
@@ -1324,7 +1370,10 @@ int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *s
13241370

13251371

13261372
HID_API_EXPORT struct hid_device_info *HID_API_CALL hid_get_device_info(hid_device *dev) {
1327-
if (!dev->device_info) {
1373+
if (dev->device_info) {
1374+
register_device_error(dev, NULL);
1375+
}
1376+
else {
13281377
// Lazy initialize device_info
13291378
dev->device_info = create_device_info_for_hid_device(dev);
13301379
}
@@ -1339,6 +1388,7 @@ int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index
13391388
(void)string;
13401389
(void)maxlen;
13411390

1391+
errno = ENOSYS;
13421392
register_device_error(dev, "hid_get_indexed_string: not supported by hidraw");
13431393

13441394
return -1;
@@ -1348,6 +1398,15 @@ int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index
13481398
int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size)
13491399
{
13501400
struct hidraw_report_descriptor rpt_desc;
1401+
1402+
if (!buf || !buf_size) {
1403+
errno = EINVAL;
1404+
register_device_error(dev, "Zero buffer/length");
1405+
return -1;
1406+
}
1407+
1408+
register_device_error(dev, NULL);
1409+
13511410
int res = get_hid_report_descriptor_from_hidraw(dev, &rpt_desc);
13521411
if (res < 0) {
13531412
/* error already registered */

mac/hid.c

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,13 +1105,13 @@ static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char
11051105
IOReturn res;
11061106
unsigned char report_id;
11071107

1108-
register_device_error(dev, NULL);
1109-
11101108
if (!data || (length == 0)) {
1111-
register_device_error(dev, strerror(EINVAL));
1109+
register_device_error(dev, "Zero buffer/length");
11121110
return -1;
11131111
}
11141112

1113+
register_device_error(dev, NULL);
1114+
11151115
report_id = data[0];
11161116

11171117
if (report_id == 0x0) {
@@ -1145,10 +1145,17 @@ static int get_report(hid_device *dev, IOHIDReportType type, unsigned char *data
11451145
unsigned char *report = data;
11461146
CFIndex report_length = length;
11471147
IOReturn res = kIOReturnSuccess;
1148-
const unsigned char report_id = data[0];
1148+
unsigned char report_id;
1149+
1150+
if (!data || (length == 0)) {
1151+
register_device_error(dev, "Zero buffer/length");
1152+
return -1;
1153+
}
11491154

11501155
register_device_error(dev, NULL);
11511156

1157+
report_id = data[0];
1158+
11521159
if (report_id == 0x0) {
11531160
/* Not using numbered Reports.
11541161
Don't send the report number. */
@@ -1240,13 +1247,17 @@ static int cond_timedwait(hid_device *dev, pthread_cond_t *cond, pthread_mutex_t
12401247
}
12411248

12421249
return 0;
1243-
12441250
}
12451251

12461252
int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
12471253
{
12481254
int bytes_read = -1;
12491255

1256+
if (!data || (length == 0)) {
1257+
register_error_str(&dev->last_read_error_str, "Zero buffer/length");
1258+
return -1;
1259+
}
1260+
12501261
register_error_str(&dev->last_read_error_str, NULL);
12511262

12521263
/* Lock the access to the report list. */
@@ -1478,7 +1489,10 @@ int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *s
14781489
}
14791490

14801491
HID_API_EXPORT struct hid_device_info *HID_API_CALL hid_get_device_info(hid_device *dev) {
1481-
if (!dev->device_info) {
1492+
if (dev->device_info) {
1493+
register_device_error(dev, NULL);
1494+
}
1495+
else {
14821496
dev->device_info = create_device_info(dev->device_handle);
14831497
if (!dev->device_info) {
14841498
register_device_error(dev, "Failed to create hid_device_info");
@@ -1501,6 +1515,13 @@ int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index
15011515

15021516
int HID_API_EXPORT_CALL hid_darwin_get_location_id(hid_device *dev, uint32_t *location_id)
15031517
{
1518+
if (!location_id) {
1519+
register_device_error(dev, "Location ID is NULL");
1520+
return -1;
1521+
}
1522+
1523+
register_device_error(dev, NULL);
1524+
15041525
int res = get_int_property(dev->device_handle, CFSTR(kIOHIDLocationIDKey));
15051526
if (res != 0) {
15061527
*location_id = (uint32_t) res;
@@ -1523,23 +1544,27 @@ int HID_API_EXPORT_CALL hid_darwin_get_open_exclusive(void)
15231544

15241545
int HID_API_EXPORT_CALL hid_darwin_is_device_open_exclusive(hid_device *dev)
15251546
{
1526-
if (!dev)
1527-
return -1;
1528-
15291547
return (dev->open_options == kIOHIDOptionsTypeSeizeDevice) ? 1 : 0;
15301548
}
15311549

15321550
int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size)
15331551
{
1552+
if (!buf || !buf_size) {
1553+
register_device_error(dev, "Zero buffer/length");
1554+
return -1;
1555+
}
1556+
1557+
register_device_error(dev, NULL);
1558+
15341559
CFTypeRef ref = IOHIDDeviceGetProperty(dev->device_handle, CFSTR(kIOHIDReportDescriptorKey));
15351560
if (ref != NULL && CFGetTypeID(ref) == CFDataGetTypeID()) {
15361561
CFDataRef report_descriptor = (CFDataRef) ref;
15371562
const UInt8 *descriptor_buf = CFDataGetBytePtr(report_descriptor);
1538-
CFIndex descriptor_buf_len = CFDataGetLength(report_descriptor);
1563+
const CFIndex descriptor_buf_len = CFDataGetLength(report_descriptor);
15391564
size_t copy_len = (size_t) descriptor_buf_len;
15401565

15411566
if (descriptor_buf == NULL || descriptor_buf_len < 0) {
1542-
register_device_error(dev, "Zero buffer/length");
1567+
register_device_error(dev, "Zero descriptor from device");
15431568
return -1;
15441569
}
15451570

windows/hid.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1474,13 +1474,16 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *de
14741474
return 0;
14751475
}
14761476

1477-
HID_API_EXPORT struct hid_device_info * HID_API_CALL hid_get_device_info(hid_device *dev) {
1477+
HID_API_EXPORT struct hid_device_info * HID_API_CALL hid_get_device_info(hid_device *dev)
1478+
{
14781479
if (!dev->device_info)
14791480
{
14801481
register_string_error(dev, L"NULL device info");
14811482
return NULL;
14821483
}
14831484

1485+
register_string_error(dev, NULL);
1486+
14841487
return dev->device_info;
14851488
}
14861489

@@ -1565,10 +1568,18 @@ int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char
15651568
return -1;
15661569
}
15671570

1571+
15681572
int res = hid_winapi_descriptor_reconstruct_pp_data(pp_data, buf, buf_size);
15691573

15701574
HidD_FreePreparsedData(pp_data);
15711575

1576+
if (res == 0) {
1577+
register_string_error(dev, NULL);
1578+
}
1579+
else {
1580+
register_string_error(dev, L"Failed to reconstruct descriptor from PREPARSED_DATA");
1581+
}
1582+
15721583
return res;
15731584
}
15741585

0 commit comments

Comments
 (0)