3

OK, I hope I explain this one correctly. I have a struct:

typedef struct _MyData
{
   char Data[256];
   int  Index;
} MyData;

Now, I run into a problem. Most of the time MyData.Data is OK with 256, but in some cases I need to expand the amount of chars it can hold to different sizes. I can't use a pointer. Is there any way to resize Data at run time? How? Code is appreciated.

EDIT 1:

While I am very thankful for all the comments, the "maybe try this..." or "do that", or "what you are dong is wrong..." comments are not helping. Code is the help here. Please, if you know the answer post the code.

Please note that:

  1. I cannot use pointers. Please don't try to figure out why, I just can't.
  2. The struct is being injected into another program's memory that's why no pointers can be used.

Sorry for being a bit rough here but I asked the question here because I already tried all the different approaches that thought might work. Again, I am looking for code. At this point I am not interested in "might work..." or " have you considered this..."

Thank you and my apologies again.

EDIT 2

Why was this set as answered?

Viktor Wolf
  • 133
  • 1
  • 10
wonderer
  • 3,487
  • 11
  • 49
  • 59
  • 13
    Why can't you use a pointer? Dynamically allocating the array is the only way to do this. –  Jul 20 '09 at 13:32
  • 1
    Either statically reserve enough space for any input into data, or you'll have to use pointers to dynamically allocate the space. There's not really any other options. – Falaina Jul 20 '09 at 13:36
  • You're already using a pointer :P – Justin Scheiner Jul 27 '09 at 13:44
  • where? if you think you have the answer please post a sample working code. thanks – wonderer Jul 27 '09 at 14:05
  • justin meant that array's are almost identical to pointers. Thats why one can say: char *DataPtr = Data; – Toad Jul 28 '09 at 08:47
  • OK. The what would be the solution? – wonderer Jul 28 '09 at 14:51
  • How about passing a pointer and the data that the pointer points to. I don't know how but is this possible? – wonderer Jul 29 '09 at 14:54
  • 3
    The upside of arrays is that they are not pointing to the data. So if you place an array into your struct, the data will start where the array starts, allowing to treat the struct + the array contained there as one single unit that you can send back and forth. If you place a pointer there, this will break. You should free yourself from seeing an array as being a pointer. The fact that you can write `char *ptr = array;` does not indicate anything: You can as-well write `char *ptr = 0;`, but still integers and pointers are two major different things. – Johannes Schaub - litb Jul 29 '09 at 16:04
  • You can't resize an array declared this way at run time. Can you explain the problem a little more. And why can't you use pointers? – hookenz Jul 30 '09 at 01:56
  • how do you pass a pointed to an injected remote thread? huh????? – wonderer Jul 30 '09 at 13:18
  • Data is a pointer. You are already using a pointer. – Pablo Fernandez Jul 30 '09 at 13:31
  • OK, then I guess I don't know how to program in C. thanks – wonderer Jul 30 '09 at 14:55
  • show me how to I do that. How do I pass a pointer to a string into a remote thread on another process space and retrieve the data without using pipes or shared memory. – wonderer Jul 30 '09 at 14:56
  • You say you didn't accept this question? I suspect it was auto-selected by timeout, but the message is usually different... but the fact that 50 rep was awarded *suggests* this... – Marc Gravell Jul 30 '09 at 22:01
  • See here for full details of the 1-week lifetime of bounty; can you remember when you added a bounty? http://blog.stackoverflow.com/2009/01/reputation-bounty-for-unanswered-questions/ – Marc Gravell Jul 30 '09 at 22:10
  • I have added a query about this on "meta": http://meta.stackexchange.com/questions/11285/bounty-message-for-timeouts-is-it-right - suggest that any of the "problem with bounty" discussion moves there... – Marc Gravell Jul 30 '09 at 22:18
  • I think I added the bounty last friday but I can't be certain. – wonderer Jul 31 '09 at 13:00
  • and I most definitely did NOT accept the answer. It doesn't work. – wonderer Jul 31 '09 at 13:01
  • @wonderer, then please tell me that it doesn't work and show your code in the question or the relevant parts as comments to my answer. We can't improve our answer if all you say is "oh, they are broke, so please NO pointers!". – Johannes Schaub - litb Jul 31 '09 at 15:26
  • ok, try creating a remote thread on another application and passing the pointer the way you suggested. Is your data accessible? If you succeed please post the code because it would be an interesting piece. – wonderer Jul 31 '09 at 16:41
  • 1
    I am *not* suggesting to use a pointer. `char Data[];` is *not* a pointer. Where do you see me suggesting a pointer in my main recommendation? Well, no offense, but i'm done with this question too, until you ask something that makes more sense. I'm not going to code a multi-threaded+distributed app just to show you that it works. – Johannes Schaub - litb Jul 31 '09 at 16:54

11 Answers11

19

You can use a flexible array member

typedef struct _MyData
{
   int  Index;
   char Data[];
} MyData;

So that you can then allocate the right amount of space

MyData *d = malloc(sizeof *d + sizeof(char[100]));
d->Data[0..99] = ...;

Later, you can free, and allocate another chunk of memory and make a pointer to MyData point to it, at which time you will have more / less elements in the flexible array member (realloc). Note that you will have to save the length somewhere, too.

In Pre-C99 times, there isn't a flexible array member: char Data[] is simply regarded as an array with incomplete type, and the compiler would moan about that. Here i recommend you two possible ways out there

  • Using a pointer: char *Data and make it point to the allocated memory. This won't be as convenient as using the embedded array, because you will possibly need to have two allocations: One for the struct, and one for the memory pointed to by the pointer. You can also have the struct allocated on the stack instead, if the situation in your program allows this.
  • Using a char Data[1] instead, but treat it as if it were bigger, so that it overlays the whole allocated object. This is formally undefined behavior, but is a common technique, so it's probably safe to use with your compiler.
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • why did you set this as an answer? it doesn't work. it crashes. – wonderer Jul 30 '09 at 21:17
  • i am using an array of chars because I CANNOT use pointers. so this solution is not a valid one. but whatever. have it your way thanks for the help – wonderer Jul 30 '09 at 21:24
  • @wonderer, what problem does occur with this answer? It recommends an array ("char Data[];"). You accepted this answer by not accepting anything else, not anyone else :) Please ask if anything is unclear about my answer, i will see what we can do. – Johannes Schaub - litb Jul 30 '09 at 23:12
  • AS I wrote in the question and subsequent comments I cannot use any kind of pointers. The reason (again) is that since I am passing that struct into another process memory I can't access the data that the pointer points to. what else do you want me to explain? – wonderer Jul 31 '09 at 12:56
  • I don't see where i recommend you to use pointers for your inter process communication. The second bullet and the main recommendation both use arrays, and the first bullet was written before you came out with that you can't use pointers. I want you to explain 1) How it crashes 2) Why the heck you keep telling me you can't use pointers . Unless you tell me that, i can't do anything. – Johannes Schaub - litb Jul 31 '09 at 15:24
  • I explained to you in the previous comment. I AM INJECTING THAT STRUCT INTO ANOTHER PROCESS. UNLESS I PASS ALL THE DATA WITHOUT USING POINTERS I WILL NOT, REPEAT, NOT HAVE ACCESS TO IT. so, unless my english is bad (which it might be) i think i am making it very clear why it would fail. but whatever, i am done. i'm treating this asnwer as impossible to do. so do whatever you want. – wonderer Jul 31 '09 at 16:43
  • The issue is as I summed up in my answer; the structure in question is used to communicate between two processes, and only one of them can be modified... therefore no change to the structure is acceptable. – Chris Arguin Aug 01 '09 at 15:24
13

The problem here is your statement "I can't use a pointer". You will have to, and it will make everything much easier. Hey, realloc even copies your existing data, what do you want more?

So why do you think you can't use a pointer? Better try to fix that.

schnaader
  • 49,103
  • 10
  • 104
  • 136
  • +1, no way to do this without pointer. It can be done only using malloc, realloc, etc. Real questions is why no pointer. – Clement Herreman Jul 20 '09 at 13:36
  • 1
    because I am passing that data to another process and everything has to be located within that struct. One I passed that data the other process has to have access to it and with pointers I can't. those two processes don't share memory. I just crash when using pointers in that struct. – wonderer Jul 20 '09 at 13:37
  • 7
    @wonderer, every IPC mechanism has some way to pass a variable amount of data. You should research how to do this with whichever mechanism you're using. – Nick Meyer Jul 20 '09 at 13:38
  • The problem is that we are dealing with a program that is not supported anymore so the only way I found to execute some code is via a DLL injection. The injection basically executes after the main call to the program is executed and also performs registry cleanup once a certain function is executed inside the "lagacy" software. I need to pass all the data contained within the structures otherwise the injected program (the legacy software) won't know where they are. – wonderer Jul 20 '09 at 17:10
  • @wonderer: Do as litb suggested then; your injected code need only know where the struct begins. – bdonlan Jul 27 '09 at 19:52
  • If you're dealing with an API that expects to see a 512-char buffer there, then you're limited to 512 chars, and that is it. There's nothing you can do about that. – Pavel Minaev Jul 29 '09 at 22:19
5

You would re-arrange the structure like that

typedef struct _MyData
{
   int  Index;
   char Data[256];
} MyData;

And allocate instances with malloc/realloc like that:

my_data = (MyData*) malloc ( sizeof(MyData) + extra_space_needed );

This is an ugly approach and I would not recommend it (I would use pointers), but is an answer to your question how to do it without a pointer.

A limitation is that it allows for only one variable size member per struct, and has to be at the end.

KIV
  • 745
  • 8
  • 12
  • yes, that will work, but you can run into a lot of problems. for example, sizeof(MyData) is not necessarily correct anymore, so default copy by value operations are going to truncate Data to 256 bytes. – Kip Jul 20 '09 at 13:41
  • 4
    If this is supposed to be C, don't cast the return value of `malloc`. http://c-faq.com/malloc/mallocnocast.html – Sinan Ünür Jul 20 '09 at 13:56
5

Let me sum up two important points I see in this thread:

  1. The structure is used to interact between two programs through some IPC mechanism
  2. The destination program cannot be changed

You cannot therefore change that structure in any way, because the destination program is stuck trying to read it as currently defined. I'm afraid you are stuck.

You can try to find ways to get the equivalent behavior, or find some evil hack to force the destination program to read a new structure (e.g., modifying the binary offsets in the executable). That's all pretty application specific so I can't give much better guidance than that.

You might consider writing a third program to act as an interface between the two. It can take the "long" messages and do something with them, and pass the "short" messages onward to the old program. You can inject that in between the IPC mechanisms fairly easily.

Chris Arguin
  • 11,850
  • 4
  • 34
  • 50
  • 1
    @wonderer: It is you actually who has been terribly wrong all along. This is the only answer to your question - what you are asking for is impossible to do. You should have marked Chris' answer as the correct one. – Kyselejsyreček Nov 26 '18 at 09:09
2

You may be able to do this like this, without allocating a pointer for the array:

typedef struct _MyData
{
    int Index;
    char Data[1];
} MyData;

Later, you allocate like this:

int bcount = 256;
MyData *foo;

foo = (MyData *)malloc(sizeof(*foo) + bcount);

realloc:

int newbcount = 512;
MyData *resized_foo;

resized_foo = realloc((void *)foo, sizeof(*foo) + newbcount);
Hasturkun
  • 35,395
  • 6
  • 71
  • 104
2

It looks like from what you're saying that you definitely have to keep MyData as a static block of data. In which case I think the only option open to you is to somehow (optionally) chain these data structures together in a way that can be re-assembled be the other process.

You'd need and additional member in MyData, eg.

typedef struct _MyData
{
   int  Sequence;
   char Data[256];
   int  Index;
} MyData;

Where Sequence identifies the descending sequence in which to re-assemble the data (a sequence number of zero would indicate the final data buffer).

Alan
  • 13,510
  • 9
  • 44
  • 50
  • I am having trouble understanding your concept. Can you post some code and explain the general idea? – wonderer Jul 29 '09 at 12:22
  • I'm saying that you could chain these data buffers together to accommodate the extra data required. eg. to pass a data that's 600 bytes in size, you would call your function (in the separate process) 3 times: Sequence 2: 256 Bytes Sequence 1: 256 Bytes Sequence 0: 88 Bytes – Alan Jul 29 '09 at 15:31
2

The problem is in the way you're putting the question. Don't think about C semantics: instead, think like a hacker. Explain exactly how you are currently getting your data into the other process at the right time, and also how the other program knows where the data begins and ends. Is the other program expecting a null-terminated string? If you declare your struct with a char[300] does the other program crash?

You see, when you say "passing data" to the other program, you might be [a] tricking the other process into copying what you put in front of it, [b] tricking the other program into letting you overwrite its normally 'private' memory, or [c] some other approach. No matter which is the case, if the other program can take your larger data, there is a way to get it to them.

egrunin
  • 24,650
  • 8
  • 50
  • 93
  • ok, think code injection. simple. get data into a struct. allocate mem, write mem, create remote thread in the injected app, run thread. – wonderer Jul 30 '09 at 13:17
  • [If you're still following this thread...] We're on the same page here, I figured you were using CreateRemoteThread(). But what I'm trying to ask is: how do you get the target program to look at your data? Are you doing a memcpy into their data areas? Are you overwriting one of their pointers to it points to your data? – egrunin Aug 18 '09 at 16:18
0

I find KIV's trick quite usable. Though, I would suggest investigating the pointer issue first.

If you look at the malloc implementations
(check this IBM article, Listing 5: Pseudo-code for the main allocator),
When you allocate, the memory manager allocates a control header and
then free space following it based on your requested size.
This is very much like saying,

typedef struct _MyData
{
   int  size;
   char Data[1]; // we are going to break the array-bound up-to size length
} MyData;

Now, your problem is,
How do you pass such a (mis-sized?) structure to this other process?

That brings us the the question,
How does the other process figure out the size of this data?
I would expect a length field as part of the communication.

If you have all that, whats wrong with passing a pointer to the other process?
Will the other process identify the difference between a pointer to a structure and that to a allocated memory?

nik
  • 13,254
  • 3
  • 41
  • 57
  • Thanks for the code. The problem is that we are dealing with a program that is not supported anymore so the only way I found to execute some code is via a simple DLL injection. The injection basically executes after the main call to the program is executed and also performs registry cleanup once a certain function is executed inside the "lagacy" software. So, unless you can give me a proper way to pass pointers into an injected function i can't use them because they crash the program – wonderer Jul 20 '09 at 17:08
  • I think I am getting a hang of what you want to do. Trouble is, you seem to be trying an 'exploit' kind of approach towards achieving your goal. This would be very dependent on the way this legacy program was written. I cannot think of any specific things to ask you that will help me figure out any scheme here `:-(` – nik Jul 20 '09 at 18:28
  • How about using something similar to FARPROC and pass the address of the pointer and get it somehow inside the injected code? – wonderer Jul 20 '09 at 18:56
0

You cant reacolate manualy.

You can do some tricks wich i was uning when i was working aon simple data holding sistem. (very simple filesystem).

typedef struct
{
    int index ;     
    char x[250];
} data_ztorage_250_char;

typedef struct
{
    int index;      
    char x[1000];
} data_ztorage_1000_char;

int main(void)
{
      char just_raw_data[sizeof(data_ztorage_1000_char)];
      data_ztorage_1000_char* big_struct;
      data_ztorage_250_char* small_struct;
      big_struct = (data_ztorage_1000_char*)big_struct; //now you have bigg struct
      // notice that upper line is same as writing 
      // big_struct = (data_ztorage_1000_char*)(&just_raw_data[0]);

      small_struct = (data_ztorage_250_char*)just_raw_data;//now you have small struct

      //both structs starts at same locations and they share same memory
     //addresing data is 
      small_struct -> index = 250;
}
Luka Rahne
  • 10,336
  • 3
  • 34
  • 56
  • as I said I can't use pointers. I am passing that struct (that might have more than just an int and a char declared in it) to another program by doing an injection (the program is not supported anymore so we have no way of changing it, i am using the injection to execute code at certain places). So, all i send there HAS to be declared with the right side. No pointers. – wonderer Jul 24 '09 at 12:44
  • In that case you cant. In struct itself is not writen what the size of Data is. Struct define just positions at beginning of data and integer and writing on Data[256],Data[257],Data[258],Data[259] will overwrite the Index. In that case using only linker for instance, you can not tell the program that now yout integer is at different offset based on Data. – Luka Rahne Jul 24 '09 at 13:12
0

You don't state what the Index value is for.

As I understand it you are passing data to another program using the structure shown. Is there a reason why you can't break your data to send into chunks of 256bytes and then set the index value accordingly? e.g.

Data is 512 bytes so you send one struct with the first 256 bytes and index=0, then another with the next 256 bytes in your array and Index=1.

ChrisBD
  • 9,104
  • 3
  • 22
  • 35
  • Thanks for the comments. I'm going to try to explain this again. I am trying to make an unsupported program do something that it wasn't designed to. The way to do this is to inject some code, run the code and be done with it. Some times the data i need to send to that remote thread is bigger so I need to set the size of the chars to a bigger size. I can't send the info in chunks, it all has to go at once. – wonderer Jul 30 '09 at 13:15
0

How about a really, really simple solution? Could you do:

typedef struct _MyData
{
   char Data[1024];
   int  Index;
} MyData;

I have a feeling I know your response will be "No, because the other program I don't have control over expects 256 bytes"... And if that is indeed your answer to my answer, then my answer becomes: this is impossible.

Josh
  • 10,961
  • 11
  • 65
  • 108
  • No, my answer will be: what happens if tomorrow I need to pass 2048? and the next day 100000000? – wonderer Jul 30 '09 at 18:43
  • Make it the largest conceivable size; this them becomes a limitation of your code. – Josh Jul 30 '09 at 18:47
  • Oh and of course, add error checking so if the data you need to pass is one day 100000000, you don't overwrite memory that you're not supposed to. When that day comes, increase the size of Data. – Josh Jul 30 '09 at 18:48
  • so basically i will be allocating a huge amount of memory and injecting that huge amount into another process even when I need to send only a couple hundred Ks. – wonderer Jul 30 '09 at 19:11
  • Unfortunately everyone else's suggestion was rejected -- this was the best I could think of! – Josh Jul 30 '09 at 23:31
  • Tell me that there is no answer is also a good answer. if it can't be done then there;s nothing I can do – wonderer Jul 31 '09 at 13:01