0

The following code snippet is an extraction and simplification of a running SW I am reverse engineering (I tried to emphasize the problem without bothering you with all the small details).

Building the following code on a win64 machine causes crash during operation:

#include "stdafx.h"
#include <stdio.h>
#include <string>
#include <stdlib.h>

using namespace std;

struct vaArgLookAlikePtrs 
{
    char* pPtr[1000];
};

int _tmain(int argc, _TCHAR* argv[])
{
    typedef std::basic_string<char> BasicString;
    static char buffer[132000];
    BasicString sFormatStr = "Var0=%s\nVar1=%.4f\nVar2=%d\n";
    struct vaArgLookAlikePtrs oData;

    void* pVoidPtr;
    int j=0;

    oData.pPtr[j] = "val0";
    j++;

    double dVar1 = 1.265;
    pVoidPtr = (void*)(&(oData.pPtr[j]));
    double* pDoublePtr = (double*)pVoidPtr;
    *pDoublePtr = dVar1;
    j++;// increment the buffer counter twice because doubles require 64 bits for     storage (This is how it works on the 32 bit machine)
    j++;

    int nVar2 = 2;
    pVoidPtr = &(oData.pPtr[j]);
    int* pIntPtr = (int*)pVoidPtr;
    *pIntPtr = nVar2;

    sprintf_s(buffer,sFormatStr.c_str(),oData);  // <-----

    cout << buffer << "\n";
    return 0;
}

I have few questions:

  1. Why should i increment the index (J++) twice on win32 platform? - how does win32 platform knows to "jump" over a char* point twice for a double?
  2. how come sprintf_s knows to pick the right fields from oData (a composition container) on win32? but on win64 it crashes?

I assume this is somehow with pointer sizes difference between 32 bit and 64 bit, but I'm seeking your help to explain the behavior.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
NirMH
  • 4,769
  • 3
  • 44
  • 69
  • I am not going by what code does. Just one thing: `sizeof(void*)` == 4 on 32-bit, and it is 8 on 64-bit. That means size of a pointer is 32-bit or 64-bit depending on the platform. – Ajay Jul 19 '12 at 08:10
  • 1
    `sprintf_s(buffer,sFormatStr.c_str(),oData);` this makes no sense. You are lucky it doesn't crash in 32 bits also. I think passing the wrong number of arguments to a variadic function is undefined behaviour. – RedX Jul 19 '12 at 08:16
  • Lukcy, unlucky, opinions differ. The code is broken in any case. Don't "fix" it, rewrite. It's now not even close to proper C++. – MSalters Jul 19 '12 at 08:52
  • @MSalters: you are totally right and this is my plan to rewrite it, i just wondered how come it worked and what are the reasons... – NirMH Jul 19 '12 at 10:26

2 Answers2

3

The original author just banged C statements together until it worked for him. Really, there's no other explanation for this bit of code.

MSalters
  • 173,980
  • 10
  • 155
  • 350
1

The code you posted makes no sense whatsoever. You seem to be trying to use an array as an ad-hock way to prepare variadic argument sequence for a variadic function? Sorry, it doesn't work that way neither in C nor in C++. There's simply no way to "prepare" a sequence of variadic arguments for a variadic function.

If you are trying to implement some sort of an ugly hack, then keep hacking the implementation of sprintf_s. Maybe you will get it to work somehow. But this has nothing to do with C++ language. And it is pointless at best.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765