C Struct values ​​are not assigned

I am trying to use the Video4Linux2 API , but something special is happening with the structures that I have to use to change the various controls on this camera. For some reason, some of the participants do not report changes in the appointment. To simplify the problem, I wrote the following code:

#include <getopt.h> #include <stdio.h> #include <string.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/select.h> #include <linux/videodev2.h> #include <stdlib.h> #include <errno.h> #include <stdbool.h> int setExtendedControl(int id, int value); int fd = 0; int main() { setExtendedControl(20, 30); return 0; } int setExtendedControl(int id, int value) { struct v4l2_ext_control extControl; struct v4l2_ext_controls extControls; extControl.id = id; extControl.value = value; extControl.value64 = value; extControl.reserved2[0] = 0; extControl.reserved2[1] = 0; extControl.reserved2[2] = 0; //Put the individual control structure into the //multi-control container structure and initialize the container //as well extControls.ctrl_class = V4L2_CTRL_CLASS_MPEG; extControls.count = 1; extControls.controls = &extControl; printf("extControls.controls = %i, extControl = %i\n", (extControls).controls, &extControl); extControls.reserved[0] = 0; extControls.reserved[1] = 0; extControls.reserved[2] = 0; extControls.error_idx = 0; printf("Verifying settings:\n"); printf("extControl.id = %i, id = %i\n", extControl.id, id); printf("extControl.value = %i, value = %i\n", extControl.value, value); printf("extControl.value64 = %i, value = %i\n", extControl.value64, value); printf("extControl.reserved2[0] = %i, set to 0\n", extControl.reserved2[0]); printf("extControl.reserved2[1] = %i, set to 0\n", extControl.reserved2[1]); printf("extControl.reserved2[2] = %i, set to 0\n\n", extControl.reserved2[2]); printf("extControls.ctrl_class = %i, V4L2_CTRL_CLASS_MPEG = %i\n", extControls.ctrl_class, V4L2_CTRL_CLASS_MPEG); printf("extControls.count = %i, set to 1\n", extControls.count); printf("extControls.reserved[0] = %i, set to 0\n", extControls.reserved[0]); printf("extControls.reserved[1] = %i, set to 0\n", extControls.reserved[1]); printf("extControls.reserved[2] = %i, set to 0\n", extControls.reserved[2]); printf("extControls.error_idx = %i, set to 0\n", extControls.error_idx); printf ("\nRunning secondary check..\n\n"); int rval; //Set up the individual control structure //Try to change the control and return the //value reporting the outcome. rval = ioctl(fd, VIDIOC_S_EXT_CTRLS, &extControls); if (extControls.controls != &extControl) { printf("\n\nLost the pointer on initial set!\n"); } //printf("error_idx after initial set %i\n", extControls.error_idx); //printf("extControl = %i, extControls = %i\n"); //freeStructs(extControl, extControls); return rval; } 

When I run this, the members "value" and "value64" are not set. The following is printf output:

 extControls.controls = -1954893344, extControl = -1954893344 Verifying settings: extControl.id = 20, id = 20 extControl.value = 0, value = 30 extControl.value64 = 0, value = 30 extControl.reserved2[0] = 0, set to 0 extControl.reserved2[1] = 0, set to 0 extControl.reserved2[2] = 0, set to 0 extControls.ctrl_class = 10027008, V4L2_CTRL_CLASS_MPEG = 10027008 extControls.count = 1, set to 1 extControls.reserved[0] = 0, set to 0 extControls.reserved[1] = 0, set to 0 extControls.reserved[2] = 0, set to 0 extControls.error_idx = 0, set to 0 

And here is a small snippet from gdb:

 (gdb) step printf (__fmt=0x400880 "extControls.controls = %i, extControl = %i\n") at /usr/include/x86_64-linux-gnu/bits/stdio2.h:105 105 return __printf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __va_arg_pack ()); (gdb) step setExtendedControl (id=20, value=30) at ioctlTest.c:30 30 extControl.reserved2[0] = 0; (gdb) step Hardware watchpoint 2: extControl Old value = {id = 4294960502, size = 32767, reserved2 = {4196309}, {value = 0, value64 = 67750802696962048, string = 0xf0b2ff00000000 <Address 0xf0b2ff00000000 out of bounds>}} New value = {id = 20, size = 32767, reserved2 = {0}, {value = 0, value64 = 67750802696962048, string = 0xf0b2ff00000000 <Address 0xf0b2ff00000000 out of bounds>}} 

This does not happen here, but there were other cases in a more rigid version of this code, where a pointer to extControls.controls and an int assignment of the extControl.id member are assigned. What could lead to the failure of the assignment of an element of a structure of this kind?

Thanks in advance!

+4
source share
2 answers

I can’t check it myself, but looking at the specification of struct v4l2_ext_control (Table 1), he says:

Table 1. struct v4l2_ext_control

 __u32 id Identifies the control, set by the application. __u32 reserved2[2] Reserved for future extensions. Drivers and applications must set the array to zero. union (anonymous) __s32 value New value or current value. __s64 value64 New value or current value. void * reserved Reserved for future pointer-type controls. Currently unused. 

Pay attention to three things here:

  • value and value64 are part of the union, they occupy the same place in memory
  • reserved2 has a size of two, therefore only reserved2[0] , reserved2[1] , no reserved2[2] !
  • according to this specification, the memory address reserved precedes the union within the structure

That means when you install

 extControl.reserved2[2] = 0; 

you are actually writing outside the memory allocated to this array, overwriting the union data, thereby changing both the value and value64 elements at the same time.

+3
source

See kernel docs for structure information.

The reserved[] array for the v4l2_ext_control structure has a length of 2 ... so you change the memory, which should not be with the line:

extControl.reserved2[2] = 0;

+3
source

All Articles