Skip to content

Conversation

@estyrke
Copy link
Contributor

@estyrke estyrke commented Oct 5, 2020

substr() creates a temporary string which will be deallocated, leaving the c_str() pointer pointing to garbage.

To see the logs from the Cloud Build CI, please join either our discussion or announcement mailing list.


This change is Reviewable

substr() creates a temporary string which will be deallocated, leaving the c_str() pointer pointing to garbage.
Copy link
Collaborator

@pyu10055 pyu10055 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 0 of 1 approvals obtained (waiting on @estyrke)


tfjs-node/binding/tfjs_backend.cc, line 1142 at r1 (raw file):

      input_tensor_index = 0;
    } else {
      input_tensor_index = atoi(input_op_index.c_str());

Is the concern that the temporary string was not disposed? If so here the temporary string is created?

@estyrke
Copy link
Contributor Author

estyrke commented Oct 6, 2020

Reviewable status: 0 of 1 approvals obtained (waiting on @estyrke)

tfjs-node/binding/tfjs_backend.cc, line 1142 at r1 (raw file):

      input_tensor_index = 0;
    } else {
      input_tensor_index = atoi(input_op_index.c_str());

Is the concern that the temporary string was not disposed? If so here the temporary string is created?

Not exactly. The problem is on this line:

const char *input_op_index = name.substr(index + 1).c_str();

The expression name.substr(index + 1) creates a temporary variable whose scope ends at the end of the "full-expression" (essentially the end of this line). The c_str() call then takes the address of the string pointed to by this temporary variable. Thus, after this line, the pointer in input_op_index points to an already deallocated memory area. When the pointer is then used on the line you pointed out, the result is undefined. In most cases, the memory contents may still be there and no problem is observed. But if the deallocated memory area has already been cleared or reused, the atoi (or the strlen before it) will fail. This is what we observed on our compiler (VS 2019) - the strlen returns 0 and the output_tensor_index (in our case) will always be zero no matter which output we try to select.

In general, it is risky to hold on to the value returned by c_str, since it is an unmanged C pointer which will be undefined if used after its backing std::string has been deallocated - It is better to only call it "temporarily" when it is needed, such as within the atoi call here.

@estyrke
Copy link
Contributor Author

estyrke commented Oct 6, 2020

VC2019 prints a warning to this effect, unfortunately I don't have a windows computer at hand now so I can't quote it.

Copy link
Collaborator

@pyu10055 pyu10055 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: :shipit: complete! 1 of 1 approvals obtained (waiting on @estyrke)


tfjs-node/binding/tfjs_backend.cc, line 1142 at r1 (raw file):

Previously, estyrke (Emil Styrke) wrote…

Not exactly. The problem is on this line:

const char *input_op_index = name.substr(index + 1).c_str();

The expression name.substr(index + 1) creates a temporary variable whose scope ends at the end of the "full-expression" (essentially the end of this line). The c_str() call then takes the address of the string pointed to by this temporary variable. Thus, after this line, the pointer in input_op_index points to an already deallocated memory area. When the pointer is then used on the line you pointed out, the result is undefined. In most cases, the memory contents may still be there and no problem is observed. But if the deallocated memory area has already been cleared or reused, the atoi (or the strlen before it) will fail. This is what we observed on our compiler (VS 2019) - the strlen returns 0 and the output_tensor_index (in our case) will always be zero no matter which output we try to select.

In general, it is risky to hold on to the value returned by c_str, since it is an unmanged C pointer which will be undefined if used after its backing std::string has been deallocated - It is better to only call it "temporarily" when it is needed, such as within the atoi call here.

got it, thanks for the explanation.

@pyu10055 pyu10055 merged commit e2f9ad3 into tensorflow:master Oct 6, 2020
lina128 pushed a commit to lina128/tfjs that referenced this pull request Oct 7, 2020
BUG
substr() creates a temporary string which will be deallocated, leaving the c_str() pointer pointing to garbage.

Co-authored-by: Ping Yu <4018+pyu10055@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants