I'm trying to use the Video4Linux2 API, but something peculiar is happening with the structs that I'm supposed to use to change the various controls on a given camera. For some reason, some of the members aren't reporting back as changed on assignment. I wrote the following code to simplify the problem:
#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 "value" and "value64" members aren't set. The following is the printf outputs:
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>}}
It's not happening here, but there have been other instances in a beefier version of this code where the pointer assignment for extControls.controls and int assignment of member extControl.id both fail. What would cause a struct member assignment failure of this nature?
Thanks in advance!
Can't check this myself, but looking at this spec of struct v4l2_ext_control (Table 1), it 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.
Note three things here:
value and value64 are part of a union, they occupy the same location in memory
reserved2 has size two, so only, reserved2[0], reserved2[1], no reserved2[2] !
according to this spec, reserved memory address precedes the union within the struct
This means that when you set
extControl.reserved2[2] = 0;
you are actually writing outside the memory assigned to that array, overwriting the data of the union, thus altering "both" value and value64 members at the same time.
See kernel docs for struct information
The reserved[] array for the v4l2_ext_control struct is only of length 2...so you're modifying memory that you shouldn't be with the line:
extControl.reserved2[2] = 0;
Related
I'm using OLE DB to retrieve some data from a SQL server, the outline of the code is
m_spCmd->SetCommandText(DBGUID_DEFAULT,L"SELECT * FROM sys.DM_OS_PERFORMANCE_COUNTERS"); // S_OK
CComPtr<IRowset> result;
m_spCmd->Execute(nullptr,__uuidof(IRowset),nullptr,nullptr,(IUnknown**)&result); // S_OK
DBCOUNTITEM fetched;
HROW *hrow;
result->GetNextRows(DB_NULL_HCHAPTER,0,1,&fetched,&hrow); // A
at A , I got an access violation exception (which means something is null, the result itself is not null). I think I have missed some step(s) in the code, what's that? Many thanks!!!
Update
sqlcmd.h
#pragma once
#include <windows.h>
#include <msdaguid.h>
#include <msdasql.h>
#include <oledb.h>
#include <oledberr.h>
#include <iostream>
#include <atlbase.h>
#include <atldbcli.h>
using namespace std;
struct SQLCmd
{
SQLCmd();
~SQLCmd();
private:
template<typename T> void print(T);
private:
CComPtr<IDBInitialize> m_spDb;
CComPtr<IDBProperties> m_spDbProperty;
CComPtr<ISessionProperties> m_spSsProperty;
CComPtr<ICommandText> m_spCmd;
CComPtr<ISQLErrorInfo> m_spErr;
CComPtr<IAccessor> m_spAccessor;
CComPtr<IDBCreateSession> m_spCrsession;
HRESULT hr;
};
sqlcmd.cpp
#include "sqlcmd.h"
template<>
void SQLCmd::print(CComPtr<IRowset> ptr)
{
DBORDINAL count;
DBCOLUMNINFO *info;
OLECHAR *buf;
auto accessor = CComQIPtr<IAccessor>(ptr);
auto colinfo = CComQIPtr<IColumnsInfo>(ptr);
colinfo->GetColumnInfo(&count,&info,&buf);
/*
DBBINDING *bindings = new DBBINDING[count];
memset(bindings,0,sizeof(DBBINDING)*count);
DBBINDSTATUS *bindingstatus = new DBBINDSTATUS[count];
memset(bindingstatus,0,sizeof(DBBINDSTATUS)*count);
DBBYTEOFFSET offset = 0;
int rowsize = 0;
for(int i = 0 ; i < count ; i++)
{
auto &[pwszName,pTypeInfo,iOrdinal,dwFlags,ulColumnSize,wType,bPrecision,bScale,columnid] = info[i];
bindings[i].iOrdinal = iOrdinal;
bindings[i].obValue = offset;
bindings[i].wType = wType;
bindings[i].dwPart = DBPART_VALUE;
bindings[i].bPrecision = bPrecision;
bindings[i].bScale = bScale;
offset += ulColumnSize;
rowsize += ulColumnSize;
printf("%ws %lld %d\n",pwszName,ulColumnSize,wType);
}
HACCESSOR haccessor;
hr = accessor->CreateAccessor(DBACCESSOR_ROWDATA,count,bindings,rowsize,&haccessor,bindingstatus);
printf("CreateAccessor %x %llx\n",hr,haccessor);
for(int i = 0 ; i < count ; i++)
if(DBBINDSTATUS_OK != bindingstatus[i])
printf("%d - %d\n",i,bindingstatus[i]);*/
DBCOUNTITEM fetched;
HROW *hrow;
printf("before GetNextRows\n");
hr = ptr->GetNextRows(DB_NULL_HCHAPTER,0,1,&fetched,&hrow);
printf("GetNextRows %x %lld\n",hr,fetched);
}
SQLCmd::SQLCmd()
{
GUID msoledbsql;
CLSIDFromString(L"{5A23DE84-1D7B-4A16-8DED-B29C09CB648D}",&msoledbsql);
m_spDb.CoCreateInstance(msoledbsql);
m_spDbProperty = CComQIPtr<IDBProperties>(m_spDb);
CDBPropSet set(DBPROPSET_DBINIT);
set.AddProperty(DBPROP_AUTH_INTEGRATED,L"SSPI");
set.AddProperty(DBPROP_INIT_CATALOG,L"master");
set.AddProperty(DBPROP_INIT_DATASOURCE,L"localhost");
m_spDbProperty->SetProperties(1,&set);
m_spDb->Initialize();
auto m_spCrsession = CComQIPtr<IDBCreateSession>(m_spDb);
if (!!m_spCrsession)
{
hr = m_spCrsession->CreateSession(nullptr,__uuidof(ISessionProperties),(IUnknown**)&m_spSsProperty);
auto _ = CComQIPtr<IDBCreateCommand>(m_spSsProperty);
if (!!_)
hr = _->CreateCommand(nullptr,__uuidof(ICommandText),(IUnknown**)&m_spCmd);
}
CComPtr<IRowset> result;
hr = m_spCmd->SetCommandText(DBGUID_DEFAULT,L"SELECT * FROM sys.DM_OS_PERFORMANCE_COUNTERS");
printf("SetCommandText 0x%x\n",hr);
DBROWCOUNT rowcount;
hr = m_spCmd->Execute(nullptr,__uuidof(IRowset),nullptr,&rowcount,(IUnknown**)&result);
printf("Execute 0x%x %lld\n",hr,rowcount);
if (!!result)
{
print(result);
}
}
SQLCmd::~SQLCmd()
{
if (!!m_spDb) m_spDb->Uninitialize();
}
test.cpp
#include "sqlcmd.h"
int main()
{
CoInitialize(nullptr);
SQLCmd cmd;
}
compile
cl /nologo /EHsc /std:c++latest test.cpp sqlcmd.cpp /link /debug
run
>test
SetCommandText 0x0
Execute 0x0 -1
before GetNextRows
IRowset::GetNextRows documentation: says this
If *prghRows is not a null pointer on input, it must be a pointer to
consumer-allocated memory large enough to return the handles of the
requested number of rows. If the consumer-allocated memory is larger
than needed, the provider fills in as many row handles as specified by
pcRowsObtained; the contents of the remaining memory are undefined.
So you can't pass a random pointer on input. You must set it to something valid or NULL:
HROW* hrow = NULL;
I am attempting to create a custom system call that inputs an (long) array and outputs some basic information about this array for a class assignment.
I am having some trouble passing the appropriate arguments into the system call.
Below is the test program I am using to debug this system call:
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include "array_stats.h"
#define _ARRAY_STATS_ 341 // for a 64 bit system
int main () {
struct array_stats * stats;
long ary[3];
ary[0] = 1;
ary[1] = 2;
ary[2] = 3;
long s = 3;
printf("\nDiving to kernel level\n\n");
// Calling array_stats syscall
int result = syscall(_ARRAY_STATS_, &stats, ary, s);
printf("\nRising to user level w/ result = %d\n\n", result);
return 0;
}
Here is the array_stats system call, I have inserted a bunch of printk() statements for debugging purposes:
#include <linux/kernel.h>
#include <asm/errno.h>
#include <linux/uaccess.h>
#include "array_stats.h"
asmlinkage long sys_array_stats (struct array_stats *stats, long data[], long size) {
printk("1. %s\n", "System call started");
long loc_max;
long loc_min;
long loc_sum;
long local_data[size];
int i = 1;
int result = 0;
printk("2. %s\n", "Variables created");
printk("Size %lu\n", size);
printk("data[0] = %lu\n", data[0]);
printk("data[1] = %lu\n", data[1]);
printk("data[2] = %lu\n", data[2]);
if (size <= 0) return -EINVAL;
printk("3. %s\n", "Size validated");
result = copy_from_user (local_data, data, size * sizeof * data);
if (!result) return EFAULT;
loc_max = local_data[0];
loc_min = local_data[0];
loc_sum = local_data[0];
for (; i < loc_sum; i++) {
loc_sum += local_data[i];
if (local_data[i] < loc_min) loc_min = local_data[i];
if (local_data[i] > loc_max) loc_max = local_data[i];
}
stats -> min = loc_min;
stats -> max = loc_max;
stats -> sum = loc_sum;
printk("Min: %lu\n", loc_min);
printk("Max: %lu\n", loc_max);
printk("Sum: %lu\n", loc_sum);
return result;
}
The running of the test program results in the following:
root#debian-amd64:~# ./array_stats_test
Diving to kernel level
[ 92.735994] 1. System call started
[ 92.737851] 2. Variables created
[ 92.738037] Size 0
[ 92.738155] data[0] = 0
[ 92.738417] data[1] = 6955032
[ 92.738565] data[2] = 0
Rising to user level w/ result = -1
root#debian-amd64:~#
As you can see, the arguments aren't being passed in properly. What am I doing wrong?
Thanks in advance!
I'm using the LXLE 14.04 distribution of Linux. I want to write a C program to read commands, interpret and perform them. I'd like the program to be efficient, and I do not want to use a linked list. The commands are operations on sets. Each set can contain any of the values from 0 through 127 inclusive. I decided to represent a set as an array of characters, containing 128 bits. If bit at position pos is turned on then the number pos is in the set and if the bit at position pos is turned off then the number pos is not present in the set. For example, if the bit at position 4 is 1, then the number 4 is present in the set, if the bit at position 11 is 1 then the number 11 is present in the set.
The program should read commands and interpret them in a certain way. There are a few commands: read_set, print_set, union_set, intersect_set, sub_set and halt.
For example, the command read_set A,1,2,14,-1 in the terminal will cause the reading of values of the list into the specified set in the command. In this case the specified set in the command is A. The end of the list is represented by -1. So after writing this command, the set A will contain the elements 1,2,14.
This is what I have so far. Below is the file set.h
#include <stdio.h>
typedef struct
{
char array[16]; /*Takes 128 bits of storage*/
}set;
extern set A , B , C , D , E , F;
This is the file main.c
#include <stdio.h>
#include "set.h"
#include <string.h>
#include <stdlib.h>
set A , B , C , D , E , F; /*Variable definition*/
set sets[6];
/*Below I want to initialize sets so that set[0] = A set[1] = B etc*/
sets[0].array = A.array;
sets[1].array = B.array;
sets[2].array = C.array;
sets[3].array = D.array;
sets[4].array = E.array;
sets[5].array = F.array;
void read_set(set s,char all_command[])
{
int i, number = 0 , pos;
char* str_num = strtok(NULL,"A, ");
unsigned int flag = 1;
printf("I am in the function read_set right now\n");
while(str_num != NULL) /*without str_num != NULL get segmentation fault*/
{
number = atoi(str_num);
if(number == -1)
return;
printf("number%d ",number);
printf("str_num %c\n",*str_num);
i = number/8; /*Array index*/
pos = number%8; /*bit position*/
flag = flag << pos;
s.array[i] = s.array[i] | flag;
str_num = strtok(NULL, ", ");
if(s.array[i] & flag)
printf("Bit at position %d is turned on\n",pos);
else
printf("Bit at position %d is turned off\n",pos);
flag = 1;
}
}
typedef struct
{
char *command;
void (*func)(set,char*);
} entry;
entry chart[] = { {"read_set",&read_set} };
void (*getFunc(char *comm) ) (set,char*)
{
int i;
for(i=0; i<2; i++)
{
if( strcmp(chart[i].command,comm) == 0)
return chart[i].func;
}
return NULL;
}
int main()
{
#define PER_CMD 256
char all_comm[PER_CMD];
void (*ptr_one)(set,char*) = NULL;
char* comm; char* letter;
while( (strcmp(all_comm,"halt") != 0 ) & (all_comm != NULL))
{
printf("Please enter a command");
gets(all_comm);
comm = strtok(all_comm,", ");
ptr_one = getFunc(comm);
letter = strtok(NULL,",");
ptr_one(sets[*letter-'A'],all_comm);
all_comm[0] = '\0';
letter[0] = '\0';
}
return 0;
}
I defined a command structure called chart that has a command name and function pointer for each command. Then I have created an array of these
structures which can be matched within a loop.
In the main function, I've created a pointer called ptr_one. ptr_one holds the value of the proper function depending on the command entered by the user.
The problem is, that since user decides which set to use,I need to represent the sets as some variable, so that different sets can be sent to the function ptr_one. I thought about
creating an array in main.c like so
set sets[6];
sets[0] = A;
sets[1] = B;
sets[2] = C;
sets[3] = D;
sets[4] = E;
sets[5] = F;
And then call the function ptr_one in the main function like this ptr_one(sets[*letter-'A'] , all_command).
That way, I convert my character into a set.
The problem is that while writing the above code I got the following compile error:
error: expected ���=���, ���,���, ���;���, ���asm��� or ���attribute��� before ���.��� token
I also tried the following in the file main.c
sets[0].array = A.array;
sets[1].array = B.array;
sets[2].array = C.array;
sets[3].array = D.array;
sets[4].array = E.array;
sets[5].array = F.array;
But I got this compile error expected ���=���, ���,���, ���;���, ���asm��� or ���attribute��� before ���.��� token
I know similar questions have been asked, by they don't seem to help in my
specific case. I tired this set sets[6] = { {A.array},{B.array},{C.array},{D.array},{E.array},{F.array} } too but it did not compile.
What's my mistake and how can I initialize sets so that it holds the sets A though F?
[EDIT] I have changed my program so I no longer need to use XGetSelectionOwner(), so I no longer need an answer. Should I delete this post? [END-EDIT]
I want to get the ID of the App's main window that has the current selection, to save, so after doing something with the selection I can then raise/activate/focus the original App.
What is returned by XGetSelectionOwner()?
[EDIT] How do I get the program main window ID from this?
[EDIT2] Added stripped down code with its output:
//Filter and Read Selected Text with ReadPlease
// g++ RP.c -lX11 -o RPo
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#define MAX_PROPERTY_VALUE_LEN 4096
typedef unsigned long ulong;
static void Get_CL(Display *);
static Window *get_client_list(Display *, ulong *);
static char *get_property(Display *, Window, Atom , const char *, ulong *);
int main(void)
{
// Open the Display
Display *dsp = XOpenDisplay(NULL);
// Show the client window list with ids and names
Get_CL(dsp);
// Get the selection window
Window swn = XGetSelectionOwner(dsp, XA_PRIMARY);
printf("s = 0x%08lx\n", swn);
if(!swn) {
exit(0);
}
Window parent_win; // ID of the parent window of our window
Window root_win; // root window of the screen our window is mapped on
Window* child_windows; // array of IDs of the child windows
uint num_child_windows;
/* finally, make the query for the above values. */
XQueryTree(dsp, swn,
&root_win,
&parent_win,
&child_windows, &num_child_windows);
printf("r = 0x%08lx p = 0x%08lx c = %d\n",
root_win, parent_win, num_child_windows);
// Get the selection
// <snip>
if(swn) {
// What window do I need here?
XSetInputFocus(dsp, swn, RevertToParent, CurrentTime);
printf("s = 0x%08lx\n", swn);
}
XCloseDisplay(dsp);
}
static void Get_CL(Display *dsp)
{
// Get client list
ulong client_list_size;
static Window *cl = get_client_list (dsp, &client_list_size);
int cls = client_list_size / sizeof(Window);
for (int i = 0; i < cls; i++) {
char *wm_name = get_property(dsp, cl[i], XA_STRING, "WM_NAME", NULL);
printf("w = 0x%08lx N = %s\n", cl[i], wm_name);
XFree(wm_name);
}
XFree(cl);
}
static Window *get_client_list(Display *disp, ulong *size) {
Window *client_list;
if ((client_list = (Window *)get_property(disp, DefaultRootWindow(disp),
XA_WINDOW, "_NET_CLIENT_LIST", size)) == NULL) {
return NULL;
}
return client_list;
}
static char *get_property (Display *disp, Window win,
Atom xa_prop_type, const char *prop_name, ulong *size) {
Atom xa_prop_name;
Atom xa_ret_type;
int ret_format;
ulong ret_nitems;
ulong ret_bytes_after;
ulong tmp_size;
unsigned char *ret_prop;
char *ret;
xa_prop_name = XInternAtom(disp, prop_name, False);
if (XGetWindowProperty(disp, win, xa_prop_name, 0,
MAX_PROPERTY_VALUE_LEN / 4, False,
xa_prop_type, &xa_ret_type, &ret_format,
&ret_nitems, &ret_bytes_after, &ret_prop) != Success) {
printf("Cannot get %s property.\n", prop_name);
return NULL;
}
if (xa_ret_type != xa_prop_type) {
printf("Invalid type of %s property.\n", prop_name);
XFree(ret_prop);
return NULL;
}
/* null terminate the result to make string handling easier */
tmp_size = (ret_format / 8) * ret_nitems;
/* Correct 64 Architecture implementation of 32 bit data */
if(ret_format==32) tmp_size *= sizeof(long)/4;
ret = (char *)malloc(tmp_size + 1);
memcpy(ret, ret_prop, tmp_size);
ret[tmp_size] = '\0';
if (size) {
*size = tmp_size;
}
XFree(ret_prop);
return ret;
}
The results with nothing selected are:
owner#OP755 ~/dev/KBSim $ ./RPs
w = 0x00e00003 N = Bottom Expanded Edge Panel
w = 0x0220001c N = x-caja-desktop
w = 0x03e0008e N = meld - What are "synchronzation points"? - Stack Overflow - Mozilla Firefox
w = 0x03600082 N = RP_snip.c (~/dev/KBSim) - pluma
w = 0x04200003 N = Terminal
w = 0x03602154 N = Find
w = 0x02353596 N = owner
w = 0x03c00002 N = ReadPlease Plus 2003
w = 0x03c00004 N = ReadPlease Plus 2003: .\Help\rpInstructions.txt
s = 0x00000000
And with a selection:
owner#OP755 ~/dev/KBSim $ ./RPs
w = 0x00e00003 N = Bottom Expanded Edge Panel
w = 0x0220001c N = x-caja-desktop
w = 0x03e0008e N = meld - What are "synchronzation points"? - Stack Overflow - Mozilla Firefox
w = 0x03600082 N = RP_snip.c (~/dev/KBSim) - pluma
w = 0x04200003 N = Terminal
w = 0x03602154 N = Find
w = 0x02353596 N = owner
w = 0x03c00002 N = ReadPlease Plus 2003
w = 0x03c00004 N = ReadPlease Plus 2003: .\Help\rpInstructions.txt
s = 0x03e034c2
r = 0x0000007d p = 0x0000007d c = 0
s = 0x03e034c2
X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 42 (X_SetInputFocus)
Serial number of failed request: 21
Current serial number in output stream: 23
owner#OP755 ~/dev/KBSim $
The line:
r = 0x0000007d p = 0x0000007d c = 0
shows the root, parent (and no children) windows.
The root and parent are the same, and do not change if I make a selection in a different program.
I hope someone can make sense out of my poor code.
I am programming on some device and I encountered
rather strange situation.
The same variable - for the first time has correct value,
but the SAME variable on a different place in code,
has a DIFFERENT value.
What can be causing this? I am pretty sure I didn't modify
the variable in between, I am also pretty sure I didn't
modify the variable using some pointers accidentally.
What can be causing this? I am really confused?
Can it be related that I for example used whole available stack
space of some function - and because of this compiler automatically
0-ifies my variable(or something similar)?
I have some long code inside a single function f.
Here's whole details on usage of pointsEntered variable in my code (how it is used).
/* Let the user input points */
s32 pointsEntered = 0;
int pointsCounter = 0;
while(1)
{
if(pointsCounter == 3)
return; // User entered wrong points 3 times, exit function
bool retStatus = false;
retStatus = inputPoints(&pointsEntered);
if(false == retStatus) // If user didn't enter amount, exit this function
return;
if(pointsEntered>atoi(userAmount)){
PromptBox(false, 0, "Points should not be more\n than current points");
pointsCounter++;
continue;
}
break;
}
// PROBLEM: pointsEntered - is OK here but as it will be shown below, it gets modified down the way
// even though I don't change it directly
char intTest1[50];
sprintf(intTest1, "1pentered %d", pointsEntered); // Here the value is OK! It shows value that I entered, e.g., 220
PromptBox(false, 0, intTest1);
/* Let the user enter 4 digit pin code */
u8 pinEntered[5] = {0};
bool retStatus1 = false;
retStatus1 = inputPin(pinEntered);
pinEntered[5]='\0';
if(false == retStatus1) // If user didn't enter amount, exit this function
return;
char intTest2[50];
sprintf(intTest2, "2pentered %d", pointsEntered); // Here pointsEnetered is OK
PromptBox(false, 0, intTest2);
/* Compute hash of pin code*/
s32 siRet1 = 0;
u8 pinVerify[25]={0};
u8 hashResult[16] = {0};
memcpy(pinVerify,pinEntered,4);
memcpy(&pinVerify[4],"XXXX",21);
siRet1 = sdkMD5(hashResult,pinVerify,25);
char intTest3[50];
sprintf(intTest3, "3pentered %d", pointsEntered); // Here pointsEntered has changed!!!
PromptBox(false, 0, intTest3);
/* convert string hash code to byte array */
unsigned char val[16] = {0};
unsigned char * pos = pinHash;
size_t count = 0;
// WARNING: no sanitization or error-checking whatsoever
for(count = 0; count < sizeof(val)/sizeof(val[0]); count++)
{
sscanf(pos, "%2hhx", &val[count]);
pos += 2 * sizeof(char);
}
char intTest4[50];
sprintf(intTest4, "4pentered %d", pointsEntered);
PromptBox(false, 0, intTest4);
/* Does the pin hash match ? */
if (siRet == SDK_OK && (!memcmp(hashResult,val,16)))
{
MsgBox("PIN OK","",0,SDK_KEY_MASK_ESC | SDK_KEY_MASK_ENTER);
}
else
{
MsgBox("PIN doesn't match-exiting","",0,SDK_KEY_MASK_ESC | SDK_KEY_MASK_ENTER);
return;
}
char intTest[50];
sprintf(intTest, "pentered %d", pointsEntered);
PromptBox(false, 0, intTest);
These two lines may cause it (as it's undefined behavior):
u8 pinEntered[5] = {0};
...
pinEntered[5]='\0';
Here you declare an array of five entries, but then you assign to a sixth item. This will most likely overwrite any previous variable on the stack.