Skip to content

Commit 636628d

Browse files
authored
[clang] Enforce 1-based indexing for command line source locations (llvm#139457)
Fixes llvm#139375 Clang expects command line source locations to be provided using 1-based indexing. Currently, Clang does not reject zero as invalid argument for column or line number, which can cause Clang to crash. This commit extends validation in `ParsedSourceLocation::FromString` to only accept (unsinged) non-zero integers.
1 parent a2f156b commit 636628d

File tree

7 files changed

+54
-5
lines changed

7 files changed

+54
-5
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,11 @@ clang-format
859859
- Add ``OneLineFormatOffRegex`` option for turning formatting off for one line.
860860
- Add ``SpaceAfterOperatorKeyword`` option.
861861

862+
clang-refactor
863+
--------------
864+
- Reject `0` as column or line number in 1-based command-line source locations.
865+
Fixes crash caused by `0` input in `-selection=<file>:<line>:<column>[-<line>:<column>]`. (#GH139457)
866+
862867
libclang
863868
--------
864869
- Fixed a bug in ``clang_File_isEqual`` that sometimes led to different
@@ -877,6 +882,8 @@ libclang
877882

878883
Code Completion
879884
---------------
885+
- Reject `0` as column or line number in 1-based command-line source locations.
886+
Fixes crash caused by `0` input in `-code-completion-at=<file>:<line>:<column>`. (#GH139457)
880887

881888
Static Analyzer
882889
---------------

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,10 @@ def note_drv_verify_prefix_spelling : Note<
670670
"-verify prefixes must start with a letter and contain only alphanumeric"
671671
" characters, hyphens, and underscores">;
672672

673+
def note_command_line_code_loc_requirement
674+
: Note<"-code-completion-at=<file>:<line>:<column> requires <line> and "
675+
"<column> to be integers greater than zero">;
676+
673677
def warn_drv_global_isel_incomplete : Warning<
674678
"-fglobal-isel support for the '%0' architecture is incomplete">,
675679
InGroup<GlobalISel>;

clang/include/clang/Frontend/CommandLineSourceLoc.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ namespace clang {
2424
/// A source location that has been parsed on the command line.
2525
struct ParsedSourceLocation {
2626
std::string FileName;
27+
// The 1-based line number
2728
unsigned Line;
29+
// The 1-based column number
2830
unsigned Column;
2931

3032
public:
@@ -38,7 +40,8 @@ struct ParsedSourceLocation {
3840

3941
// If both tail splits were valid integers, return success.
4042
if (!ColSplit.second.getAsInteger(10, PSL.Column) &&
41-
!LineSplit.second.getAsInteger(10, PSL.Line)) {
43+
!LineSplit.second.getAsInteger(10, PSL.Line) &&
44+
!(PSL.Column == 0 || PSL.Line == 0)) {
4245
PSL.FileName = std::string(LineSplit.first);
4346

4447
// On the command-line, stdin may be specified via "-". Inside the
@@ -89,8 +92,12 @@ struct ParsedSourceRange {
8992
// probably belongs to the filename which menas the whole
9093
// string should be parsed.
9194
RangeSplit.first = Str;
92-
} else
95+
} else {
96+
// Column and line numbers are 1-based.
97+
if (EndLine == 0 || EndColumn == 0)
98+
return std::nullopt;
9399
HasEndLoc = true;
100+
}
94101
}
95102
auto Begin = ParsedSourceLocation::FromString(RangeSplit.first);
96103
if (Begin.FileName.empty())

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3112,9 +3112,11 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
31123112
if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) {
31133113
Opts.CodeCompletionAt =
31143114
ParsedSourceLocation::FromString(A->getValue());
3115-
if (Opts.CodeCompletionAt.FileName.empty())
3115+
if (Opts.CodeCompletionAt.FileName.empty()) {
31163116
Diags.Report(diag::err_drv_invalid_value)
3117-
<< A->getAsString(Args) << A->getValue();
3117+
<< A->getAsString(Args) << A->getValue();
3118+
Diags.Report(diag::note_command_line_code_loc_requirement);
3119+
}
31183120
}
31193121

31203122
Opts.Plugins = Args.getAllArgValues(OPT_load);
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Regression test for #139375
2+
// Clang uses 1-based indexing for source locations given from the command-line.
3+
// Verify that Clang rejects 0 as an invalid value for line or column number.
4+
5+
// RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:0:1 %s -o - 2>&1 \
6+
// RUN: | FileCheck -check-prefix=CHECK-DIAG %s
7+
// RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:1:0 %s -o - 2>&1 \
8+
// RUN: | FileCheck -check-prefix=CHECK-DIAG %s
9+
10+
// CHECK-DIAG: error: invalid value '{{.*}}' in '-code-completion-at={{.*}}'
11+
// CHECK-NEXT: hint: -code-completion-at=<file>:<line>:<column> requires <line> and <column> to be integers greater than zero
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Regression test for #139375
2+
// Clang uses 1-based indexing for source locations given from the command-line.
3+
// Verify that `clang-refactor` rejects 0 as an invalid value for line or column number.
4+
5+
// For range start:
6+
// RUN: not clang-refactor local-rename -selection=%s:0:1-1:1 -new-name=test %s 2>&1 \
7+
// RUN: | FileCheck -check-prefix=CHECK-DIAG %s
8+
// RUN: not clang-refactor local-rename -selection=%s:1:0-1:1 -new-name=test %s 2>&1 \
9+
// RUN: | FileCheck -check-prefix=CHECK-DIAG %s
10+
11+
// For range end:
12+
// RUN: not clang-refactor local-rename -selection=%s:1:1-0:1 -new-name=test %s 2>&1 \
13+
// RUN: | FileCheck -check-prefix=CHECK-DIAG %s
14+
// RUN: not clang-refactor local-rename -selection=%s:1:1-1:0 -new-name=test %s 2>&1 \
15+
// RUN: | FileCheck -check-prefix=CHECK-DIAG %s
16+
17+
// CHECK-DIAG: error: '-selection' option must be specified using <file>:<line>:<column> or <file>:<line>:<column>-<line>:<column> format, where <line> and <column> are integers greater than zero.

clang/tools/clang-refactor/ClangRefactor.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,8 @@ SourceSelectionArgument::fromString(StringRef Value) {
160160
return std::make_unique<SourceRangeSelectionArgument>(std::move(*Range));
161161
llvm::errs() << "error: '-selection' option must be specified using "
162162
"<file>:<line>:<column> or "
163-
"<file>:<line>:<column>-<line>:<column> format\n";
163+
"<file>:<line>:<column>-<line>:<column> format, "
164+
"where <line> and <column> are integers greater than zero.\n";
164165
return nullptr;
165166
}
166167

0 commit comments

Comments
 (0)